LDPとは
LDP(Label Distribution Protocol、RFC 5036)は、MPLSのラベルを隣のルータへ配るプロトコルです。経路そのものはOSPFやIS-ISが配り、LDPは「そのプレフィックスに私はこのラベルを使う」という対応だけを配ります。本記事ではLDPが隣を見つけてセッションを張りラベルを配るまでを解説し、IOS XR(XRd)のラボで確立の全過程をパケットで追います。ラベルの付け替えはMPLSのラベル操作(push / swap / pop)とPHPで解説しています。
LDPの3つの段階
LDPの動きは3つに分かれます。
| 段階 | 使うもの | やること |
|---|---|---|
| Discovery | UDP 646、宛先224.0.0.2 | Helloを撒いて隣のLSRを見つける |
| Session | TCP 646 | 見つけた相手とTCPをつなぎ、パラメータを合わせる |
| Advertisement | 同じTCP接続 | 自分のアドレスとラベルの対応を送る |
Helloだけがマルチキャストで、相手が決まってからはユニキャストのTCPに移ります。TCPを先に張りにいくのは転送アドレスが大きいほうで、小さいほうは待ち受けます。
LDP識別子
LDPは相手をLDP識別子で識別します。6オクテットで、<LSRのID>:<ラベルスペース>と表記します。
前半4オクテットはルータを一意に識別する値で、ルータIDと同じ値にすることが一般的です。後半2オクテットはラベルスペースの番号で、0はプラットフォーム全体で1つのラベル空間を使うことを表します。インタフェースごとにラベル空間を分ける構成では0以外になります。
LDPのメッセージ
RFC 5036が定義するメッセージは11種類です。タイプ値は2オクテットで、種類ごとに番号が割り当てられています。
| メッセージ | Type | 役割 |
|---|---|---|
| Notification | 0x0001 | エラーやセッションの終了を伝える |
| Hello | 0x0100 | 隣を見つける。UDPで送る唯一のメッセージ |
| Initialization | 0x0200 | セッションのパラメータを提示する |
| KeepAlive | 0x0201 | セッションを維持する |
| Address | 0x0300 | 自分が持つIPアドレスを伝える |
| Address Withdraw | 0x0301 | 伝えたアドレスを取り消す |
| Label Mapping | 0x0400 | プレフィックスとラベルの対応を伝える |
| Label Request | 0x0401 | ラベルを要求する(Downstream-on-Demandで使う) |
| Label Abort Request | 0x0402 | 出した要求を取り消す |
| Label Withdraw | 0x0403 | 配ったラベルを取り消す |
| Label Release | 0x0404 | 受け取ったラベルを返す |
このうちAddress Withdraw以降の取り消し系は、経路が消えたときやセッションが切れたときに使われます。
Addressが要る理由は、LDPの識別子とラベルを付ける宛先のIPアドレスが別物だからです。受け取った側は、Addressで教わったアドレスの一覧を使って「このネクストホップはどのLDPピアか」を対応付けます。
ラベルの配り方
IOS XRの既定はDownstream-Unsolicitedで、要求を待たずに自分のラベルを配ります。要求があってから配るDownstream-on-Demandもあり、そちらではLabel Requestを使います。配布モードの違いは別記事で解説します。
セッションが上がると、まずAddressで自分のアドレスを送り、続けて持っているプレフィックスの数だけLabel Mappingを送ります。以後は経路が増減したときに差分だけを送り、KeepAliveで接続を維持します。
DiscoveryとSessionは単位が違う
3つの段階のうち、Discoveryはリンクごと、Sessionはピアごとです。ここが対応していないため、リンクが複数あると数が一致しません。
| 項目 | Discovery | Session |
|---|---|---|
| 数の単位 | インタフェースごとに1つ | LDPピアごとに1つ |
| 使うアドレス | インタフェースのIPアドレス | 転送アドレス(通常はLoopback) |
| トランスポート | UDP 646のマルチキャスト | TCP 646のユニキャスト |
| 相手の決め方 | マルチキャストで探す | Helloで知った転送アドレスへ接続する |
| 役割 | 隣にどのLSRがいるかを知る | ラベルを運ぶ信頼できる通路を作る |
| 切れたと判断するまで | Helloのホールドタイム15秒 | セッションのホールドタイム180秒 |
PE1とP1を2本のリンクでつなぐと、Discoveryは2つ、Sessionは1本になります。LDPが相手を識別するのはLDP識別子、つまりラベルスペースの単位だからです。ラベルスペースが:0、すなわちプラットフォーム全体で1つなら、どのリンクから来ても同じラベルが有効なので、セッションを分ける理由がありません。
この非対称には運用上の意味があります。片方のリンクが落ちてもセッションは切れません。Discovery Sourceが1つ減るだけで、残った経路でTCP接続が続くためです。ラベルの再配布が起きないので、リンク障害のたびにラベルが振り直されることを避けられます。逆にすべてのリンクが落ちるとDiscovery Sourceが0になり、セッションも終了します。
実機での検証
検証環境
CE1 — PE1 — P1 — P2 — PE2 — CE2 を直列につないでいます。AS 65001のPE1 / P1 / P2 / PE2がMPLSネットワークで、OSPF(area 0、全リンクnetwork point-to-point)で経路を、LDPでラベルを配っています。CE3 / CE4はVRF CUST-Aの顧客です。
| ルータ | 役割 | Lo0 | リンク |
|---|---|---|---|
| CE1 | 顧客側(AS 65101)、192.168.1.0/24を広告 | 1.1.1.1/32 | Gi0/0/0/0 10.1.2.1 |
| PE1 | 入口 / 出口LSR(AS 65001) | 2.2.2.2/32 | Gi0/0/0/0 10.1.2.2 / Gi0/0/0/1 10.2.3.2 |
| P1 | 中継LSR | 3.3.3.3/32 | Gi0/0/0/0 10.2.3.3 / Gi0/0/0/1 10.3.4.3 |
| P2 | 中継LSR | 4.4.4.4/32 | Gi0/0/0/0 10.3.4.4 / Gi0/0/0/1 10.4.5.4 |
| PE2 | 入口 / 出口LSR(AS 65001) | 5.5.5.5/32 | Gi0/0/0/0 10.4.5.5 / Gi0/0/0/1 10.5.6.5 |
| CE2 | 顧客側(AS 65102)、192.168.6.0/24を広告 | 6.6.6.6/32 | Gi0/0/0/0 10.5.6.6 |
| CE3 | VRF CUST-Aの顧客側(AS 65107)、192.168.7.0/24を広告 | 7.7.7.7/32 | Gi0/0/0/0 10.2.7.7(PE1 Gi0/0/0/2) |
| CE4 | VRF CUST-Aの顧客側(AS 65108)、192.168.8.0/24を広告 | 8.8.8.8/32 | Gi0/0/0/0 10.5.8.8(PE2 Gi0/0/0/2) |
PE1 - P1の1リンクをキャプチャーし、LDPのやりとりをパケットで確かめます。
検証のSTEP
| STEP | 操作 | 狙い |
|---|---|---|
| 0 | 初期状態 | 定常状態のHelloとKeepAlive、LDP識別子、バインディングを確認する |
| 1 | PE1のmpls ldpからinterface Gi0/0/0/1を外し、戻す | 確立の全過程を1本のpcapに収める |
| 2 | PE1にだけLDPの認証を設定 | 認証が合わないとセッションが張れないこと。Helloは流れ続けること |
| 3 | STEP 2を削除 | STEP 0と同じに戻ること |
| 4 | PE1 - P1を2本にする | Discoveryが2つに増えてもSessionは1本のままであること |
STEP 0:初期状態
PE1から見た隣の状態です。自分のLDP識別子が2.2.2.2:0、相手が3.3.3.3:0です。
Local LDP Identifier: 2.2.2.2:0
Discovery Sources:
Interfaces:
GigabitEthernet0/0/0/1 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 10 14:56:38.298 (08:28:02 ago)xmit/recvはHelloを送受信できている状態です。ホールドタイムは15秒で、この間にHelloが届かなければ相手を失ったと判断します。
セッションの側はTCPです。show mpls ldp neighbor detailに接続の両端が出ます。
Peer LDP Identifier: 3.3.3.3:0
TCP connection: 3.3.3.3:63514 - 2.2.2.2:646
Graceful Restart: No
Session Holdtime: 180 sec
State: Oper; Msgs sent/rcvd: 590/590; Downstream-Unsolicited
Up time: 08:28:01
LDP Discovery Sources:
IPv4: (1)
GigabitEthernet0/0/0/1
IPv6: (0)
Addresses bound to this peer:
IPv4: (3)
3.3.3.3 10.2.3.3 10.3.4.3
IPv6: (0)
Peer holdtime: 180 sec; KA interval: 60 sec; Peer state: EstabP1側が63514番から接続し、PE1が646で待ち受けています。転送アドレスは3.3.3.3と2.2.2.2なので、大きいほうのP1が接続する側になりました。Addresses bound to this peerがAddressメッセージで受け取ったアドレスの一覧です。
配ったラベルと受け取ったラベルはshow mpls ldp bindingsに並びます。
2.2.2.2/32, rev 7
Local binding: label: ImpNull
Remote bindings: (1 peers)
Peer Label
----------------- ---------
3.3.3.3:0 24002
3.3.3.3/32, rev 11
Local binding: label: 24000
Remote bindings: (1 peers)
Peer Label
----------------- ---------
3.3.3.3:0 ImpNull 自分のLoopback0である2.2.2.2/32にはImpNull(implicit-null)を配っています。自分が出口なので、1つ手前でラベルを外してほしいという意味です。
キャプチャーには、5秒ごとのHelloがUDP 646のマルチキャストで、60秒ごとのKeepAliveがTCP 646のユニキャストで流れています。
STEP 1:LDPを切って戻す
PE1のmpls ldpからinterface GigabitEthernet0/0/0/1を外し、49秒後に戻しました。syslogには切断と再確立が1組だけ残ります。
RP/0/RP0/CPU0:Sep 10 23:30:49.514 UTC: mpls_ldp[1178]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 3.3.3.3:0 is DOWN (LDP IPv4 disabled on interface)
RP/0/RP0/CPU0:Sep 10 23:31:38.596 UTC: mpls_ldp[1178]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 3.3.3.3:0 is UP (IPv4 connection) キャプチャーには確立の全過程が連続して入りました。No.39からNo.47までが1回の確立です。
39 58.809799000 3.3.3.3 2.2.2.2 28509 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
41 58.830371000 2.2.2.2 3.3.3.3 646 → 28509 [SYN, ACK] Seq=0 Ack=1 Win=16384 Len=0 MSS=1240 WS=1
42 58.833393000 3.3.3.3 2.2.2.2 28509 → 646 [ACK] Seq=1 Ack=1 Win=16384 Len=0
43 58.834409000 3.3.3.3 2.2.2.2 Initialization Message
44 58.939718000 2.2.2.2 3.3.3.3 Initialization Message Keep Alive Message
45 58.943971000 3.3.3.3 2.2.2.2 Keep Alive Message
46 59.021589000 2.2.2.2 3.3.3.3 Address Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message
47 59.024623000 3.3.3.3 2.2.2.2 Address Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message Label Mapping Message TCPの3ウェイハンドシェイクが終わってから、Initializationが両方向に流れ、KeepAliveで確認し、AddressとLabel Mappingが続きます。確立からラベル配布までが0.2秒で終わっています。
Initializationの中身です。LDP識別子とセッションのパラメータが入っています。
Internet Protocol Version 4, Src: 3.3.3.3, Dst: 2.2.2.2
Version: 1
PDU Length: 68
LSR ID: 3.3.3.3
Label Space ID: 0
Message Type: Initialization Message (0x200)
Session Protocol Version: 1
Session KeepAlive Time: 180
Session Max PDU Length: 0Session KeepAlive Time: 180が提示したホールドタイムです。両者が出した値の小さいほうが採用され、その3分の1の60秒がKeepAliveの送信間隔になります。
No.46はAddressとLabel Mapping 8個が1つのTCPセグメントに入ったものです。
上で触れたパケット(No.46 Address + Label Mapping ×8)のpcapをダウンロード切断のときはNotificationが送られます。No.12には2つ入っていました。
Message Type: Notification Message (0x1)
..00 0000 0000 0000 0000 0000 0000 1001 = Status Data: Hold Timer Expired (0x9)
Message Type: Notification Message (0x1)
..00 0000 0000 0000 0000 0000 0000 1010 = Status Data: Shutdown (0xA)このキャプチャーで観測できたメッセージは6種類で、タイプ値はRFC 5036の定義と一致しました。
| 観測したメッセージ | Type |
|---|---|
| Notification | 0x0001 |
| Hello | 0x0100 |
| Initialization | 0x0200 |
| KeepAlive | 0x0201 |
| Address | 0x0300 |
| Label Mapping | 0x0400 |
残るLabel Request / Label Abort Request / Label Withdraw / Label Release / Address Withdrawは、この検証では観測していません。
STEP 2:片側だけ認証を設定する
PE1にだけLDPの認証を設定しました。DiscoveryとSessionが別の段階であることが、この状態によく現れます。
Local LDP Identifier: 2.2.2.2:0
Discovery Sources:
Interfaces:
GigabitEthernet0/0/0/1 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 10 23:31:38.337 (00:14:27 ago)Helloは認証の対象ではないのでxmit/recvのままで、相手のLDP識別子も見えています。それでもネイバーは0件です。TCPが張れないためで、キャプチャーにはSYNの再送だけが並びます。
9 11.273014000 2.2.2.2 3.3.3.3 646 → 28509 [FIN, ACK] Seq=1 Ack=19 Win=15867 Len=0
11 11.279687000 3.3.3.3 2.2.2.2 28509 → 646 [FIN, ACK] Seq=19 Ack=2 Win=15867 Len=0
16 13.302019000 3.3.3.3 2.2.2.2 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
18 15.303119000 3.3.3.3 2.2.2.2 [TCP Retransmission] 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
21 19.303361000 3.3.3.3 2.2.2.2 [TCP Retransmission] 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1
28 27.303824000 3.3.3.3 2.2.2.2 [TCP Retransmission] 29559 → 646 [SYN] Seq=0 Win=16384 Len=0 MSS=1240 WS=1PE1側は受け取ったSYNを捨てています。syslogに理由が出ます。
RP/0/RP0/CPU0:Sep 10 23:41:19.620 UTC: mpls_ldp[1178]: %ROUTING-LDP-5-NBR_CHANGE : VRF 'default' (0x60000000), Neighbor 3.3.3.3:0 is DOWN (Session MD5 password changed)
RP/0/RP0/CPU0:Sep 10 23:41:21.652 UTC: tcp[134]: %IP-TCP-3-BADAUTH : Invalid MD5 digest from 3.3.3.3:29559 to 2.2.2.2:646 for vrf:default (0x60000000) LDPの認証はTCPのMD5署名で行うため、LDPのメッセージが1つも流れないままTCPの段階で落ちます。認証の設定そのものは別記事で解説します。
STEP 3:認証を削除
設定を外すとセッションが戻り、バインディングも8件に復帰します。STEP 0と同じ状態です。
STEP 4:PE1 - P1を2本にする
PE1のGi0/0/0/3とP1のGi0/0/0/2を10.2.13.0/24でつなぎ、両方でOSPFとLDPを有効にしました。2本目のOSPFコストは100にしてあるので、転送経路は1本目のままです。
PE1のDiscovery Sourceは2つになります。
Local LDP Identifier: 2.2.2.2:0
Discovery Sources:
Interfaces:
GigabitEthernet0/0/0/1 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 11 02:59:52.792 (00:10:03 ago)
GigabitEthernet0/0/0/3 : xmit/recv
VRF: 'default' (0x60000000)
LDP Id: 3.3.3.3:0, Transport address: 3.3.3.3
Hold time: 15 sec (local:15 sec, peer:15 sec)
Established: Sep 11 02:59:52.883 (00:10:03 ago)どちらも相手は同じ3.3.3.3:0で、転送アドレスも同じ3.3.3.3です。一方でセッションは1本のままです。
Peer LDP Identifier: 3.3.3.3:0
TCP connection: 3.3.3.3:54016 - 2.2.2.2:646
Graceful Restart: No
Session Holdtime: 180 sec
State: Oper; Msgs sent/rcvd: 22/21; Downstream-Unsolicited
Up time: 00:09:50
LDP Discovery Sources:
IPv4: (2)
GigabitEthernet0/0/0/1
GigabitEthernet0/0/0/3
IPv6: (0)
Addresses bound to this peer:
IPv4: (4)
3.3.3.3 10.2.3.3 10.2.13.3 10.3.4.3
IPv6: (0)
Peer holdtime: 180 sec; KA interval: 60 sec; Peer state: EstabPeer LDP Identifierは1つ、TCP connectionも1本で、その下にLDP Discovery Sources: IPv4: (2)として2つのインタフェースが並びます。2つのDiscoveryが1つのSessionに集約されていることがこの1画面で読めます。Addresses bound to this peerが3件から4件に増えているのは、2本目のリンクのアドレス10.2.13.3をAddressメッセージで受け取ったためです。
隣接の数え方の違いは、OSPFと並べると分かりやすくなります。
| プロトコル | PE1から見たP1との隣接数 |
|---|---|
| OSPF | 2(リンクごとに隣接を張る) |
| LDP Discovery | 2(リンクごとにHello) |
| LDP Session | 1(ピアごとに1本) |
2本のリンクを同時にキャプチャーすると、流れるものがはっきり分かれます。
| リンク | Hello(UDP 646) | TCP 646のパケット |
|---|---|---|
| 1本目(10.2.3.0/24) | 65 | 12 |
| 2本目(10.2.13.0/24) | 64 | 0 |
Helloは両方に流れ、TCPは1本目にしか流れません。2本目はLDPが有効で隣も見えているのに、セッションはすでに1本目で確立しているため使われません。どちらのリンクが選ばれるかはセッションを張った時点で決まります。
キャプチャー
PE1 - P1の1リンクを採取しています。フィルターなしで取得しました。
STEP 0 定常状態
STEP 1 切断と確立
STEP 2 認証不一致
STEP 4 1本目(10.2.3.0/24)
STEP 4 2本目(10.2.13.0/24)
検証Configおよびshow結果
各STEPで8台すべてから、次の種類をルータごとに分けて取得しています。検証Configはこの..._run.txtです(最終状態は最後のSTEPのもの)。
| ファイル | 内容 |
|---|---|
..._show.txt | show version / show interface description / show route と、OSPF・LDP・MPLS転送・BGPの一式 |
..._log.txt | そのSTEPの範囲だけに絞ったshow logging |
..._run.txt | そのSTEP時点のshow running-config(=そのSTEPの検証Config) |
..._trace.txt | コア4台のLDPとLSDのトレース |
STEP 0:初期状態
| ルータ | show出力 | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 1:LDPを切って戻す
| ルータ | show出力 | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 2:片側だけ認証を設定する
| ルータ | show出力 | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 3:認証を削除(最終状態)
| ルータ | show出力 | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
STEP 4:PE1 - P1を2本にする
| ルータ | show出力 | syslog | running-config | trace |
|---|---|---|---|---|
| CE1 | show | log | run | - |
| PE1 | show | log | run | trace |
| P1 | show | log | run | trace |
| P2 | show | log | run | trace |
| PE2 | show | log | run | trace |
| CE2 | show | log | run | - |
| CE3 | show | log | run | - |
| CE4 | show | log | run | - |
参考
| RFC | タイトル | 概要 |
|---|---|---|
| RFC 5036 | LDP Specification | Discovery(2.4節)、セッション確立の状態遷移(2.5.4節)、TCP / UDPとも646番(3.10.1節)、メッセージのタイプ値。 |
| RFC 3031 | Multiprotocol Label Switching Architecture | ラベル配布プロトコルの位置づけ。 |
書籍: Luc De Ghein『MPLS Fundamentals』(Cisco Press, 2006)Chapter 4