LDPのラベル広告制御(フィルタリング)
LDPは既定で、IGPが知っているプレフィックスすべてにラベルを割り当てて配ります。しかし実際に必要なのは、BGPのネクストホップになるLoopbackの/32だけです。配るラベルを絞る3つの制御点を解説し、IOS XR(XRd)のラボで、絞っても通信が壊れないことを確かめます。LDPの基本はLDPとはで解説しています。
何を絞るのか
MPLSでパケットを運ぶとき、入口のPEが積むトランスポートラベルはBGPのネクストホップ(相手PEのLoopback)へ向かうLSPのラベルです。コアのリンクのサブネットは、そこを通過はしますがネクストホップにはならないので、ラベルを持つ必要がありません。
それでもLDPが全部に配ってしまうのは、規格が「何を配るか」を決めていないからです。RFC 5036の2.6.3節が定めるのはDownstream Unsolicited / Downstream on Demandという「いつ配るか」だけで、フィルタの仕組みはプロトコルに存在しません。何を配るかは実装ごとのローカルな方針です。
絞る理由は3つあります。ラベルテーブルが小さくなること、LDPが交換するメッセージが減ること、そして意図しないLSPを作らせないことです。
3つの制御点
ラベルは「自分のLIBに作る → 相手へ配る → 相手が受け取る」という順に流れます。IOS XRはこの3か所それぞれで止められます。
| 制御点 | 止まる場所 | 効果 |
|---|---|---|
label allocate |
作る前 | ローカルラベルを作らない。LIBそのものが小さくなる |
label advertise |
配るとき | 作るが相手に配らない。ピアごとに変えられる |
label remote accept |
受け取るとき | 受け取った分を捨てる。受ける側だけで決められる |
自分の装置のラベルテーブルを小さくしたいならlabel allocate、相手に見せたくないだけならlabel advertise、相手の設定に期待できないならlabel remote accept、という使い分けになります。
3つともmpls ldpのaddress-family ipv4配下のlabelにあり、local(自分が作る・配る)とremote(相手から受け取る)に分かれます。絞り込みの対象はルートポリシーではなくIPアクセスリストで、ピアの指定はLDP識別子(3.3.3.3:0のようにラベルスペース番号まで含む形)です。
mpls ldp
address-family ipv4
label
local
allocate for <アクセスリスト> ← 作る前に止める
advertise
to <LDP識別子> for <アクセスリスト> ← ピアごとに配る中身を決める
remote
accept
from <LDP識別子> for <アクセスリスト> ← 受け取る側で捨てるallocate forにはhost-routesというキーワードもあり、アクセスリストを書かずに「/32だけ」を指定できます。
フィルタを緩めるときはセッションのリセットが要る
一度取り下げたラベルは、フィルタを外しても自動では再広告されません。 LDPはDownstream Unsolicitedでも定期的な再送をしないため、advertiseのフィルタを消しただけでは相手のLIBは戻りません。戻すにはclear mpls ldp neighbor <相手>でセッションを張り直します。
フィルタをきつくする変更は即座に反映される(Label Withdrawが飛ぶ)のに、緩める変更は反映されない、という非対称があります。運用では、絞り込みを緩めた後にLSPが復活しない場合、設定ではなくこの性質を疑います。
検証構成
冗長性のない直列構成です。コア(PE1 - P1 - P2 - PE2)でOSPFとLDPを動かし、CE1とCE2はVRF CUST-AでPEに接続してVPNv4で疎通させます。
CE1 ------ PE1 ------ P1 ------ P2 ------ PE2 ------ CE2
(AS 65101) | | (AS 65102)
vrf CUST-A vrf CUST-A
└────── iBGP vpnv4(Lo0間)──────┘| ルータ | Lo0 | 役割 | リンク | サブネット |
|---|---|---|---|---|
| CE1 | 1.1.1.1 | AS 65101、192.168.1.0/24 | CE1 - PE1 | 10.1.2.0/24(VRF) |
| PE1 | 2.2.2.2 | 入口/出口LSR、vrf CUST-A | PE1 - P1 | 10.2.3.0/24 |
| P1 | 3.3.3.3 | 中継LSR | P1 - P2 | 10.3.4.0/24 |
| P2 | 4.4.4.4 | 中継LSR | P2 - PE2 | 10.4.5.0/24 |
| PE2 | 5.5.5.5 | 入口/出口LSR、vrf CUST-A | PE2 - CE2 | 10.5.6.0/24(VRF) |
| CE2 | 6.6.6.6 | AS 65102、192.168.2.0/24 |
グローバルのOSPFが知るのは7プレフィックスです。Lo0の/32が4本と、コアのリンクの/24が3本。PE - CEのリンクはVRFにあるためグローバルのOSPFに入らず、はじめからラベルが付きません。
検証の全体像
| STEP | 操作 | 確かめること |
|---|---|---|
| 0 | 初期状態 | 7本すべてにラベルが付いていること。ping / tracerouteが通ること |
| 1 | label allocateで/32だけに絞る(コア4台) |
LIBが7→4に縮むこと。pingとtracerouteが変わらないこと |
| 2 | label advertiseでPE1へ配る中身だけ絞る |
PE1のRemote bindingsが減り、絞っていないP2は変わらないこと |
| 3 | 送信側を外しlabel remote acceptで受信側を絞る |
P1は送っているのにPE1が持たないこと |
| 4 | すべて撤去(最終状態) | STEP 0と同じに戻ること |
疎通はCE1からping 192.168.2.1 source 192.168.1.1 count 50 timeout 1とtracerouteで各STEP測っています。
STEP 0:既定では全プレフィックスにラベルが付く
P1のローカルバインディングです。Lo0の/32が4本とリンクの/24が3本、合わせて7本すべてにラベルが割り当たっています。
RP/0/RP0/CPU0:P1#show mpls ldp bindings local
Sat Sep 12 02:38:02.240 UTC
2.2.2.2/32, rev 12
Local binding: label: 24002
3.3.3.3/32, rev 2
Local binding: label: ImpNull
4.4.4.4/32, rev 9
Local binding: label: 24000
5.5.5.5/32, rev 14
Local binding: label: 24003
10.2.3.0/24, rev 25
Local binding: label: ImpNull
10.3.4.0/24, rev 27
Local binding: label: ImpNull
10.4.5.0/24, rev 29
Local binding: label: 24001転送テーブルを見ると、その/24のラベルが使われていないことが数字で分かります。10.4.5.0/24のラベル24001はBytes Switchedが0です。
RP/0/RP0/CPU0:P1#show mpls forwarding
Sat Sep 12 02:38:03.103 UTC
Local Outgoing Prefix Outgoing Next Hop Bytes
Label Label or ID Interface Switched
------ ----------- ------------------ ------------ --------------- ------------
24000 Pop 4.4.4.4/32 Gi0/0/0/1 10.3.4.4 17265
24001 Pop 10.4.5.0/24 Gi0/0/0/1 10.3.4.4 0
24002 Pop 2.2.2.2/32 Gi0/0/0/0 10.2.3.2 1615
24003 24003 5.5.5.5/32 Gi0/0/0/1 10.3.4.4 69570 STEP 1:作る前に止める(label allocate)
コア4台に、Lo0の/32だけを許可するアクセスリストとallocate forを入れます。
ipv4 access-list LDP-LOOPBACKS
10 permit ipv4 host 2.2.2.2 any
20 permit ipv4 host 3.3.3.3 any
30 permit ipv4 host 4.4.4.4 any
40 permit ipv4 host 5.5.5.5 any
!
mpls ldp
address-family ipv4
label
local
allocate for LDP-LOOPBACKSローカルバインディングが4本になり、/24は消えます。
RP/0/RP0/CPU0:P1#show mpls ldp bindings local
Sat Sep 12 02:45:17.334 UTC
2.2.2.2/32, rev 12
Local binding: label: 24002
3.3.3.3/32, rev 2
Local binding: label: ImpNull
4.4.4.4/32, rev 9
Local binding: label: 24000
5.5.5.5/32, rev 14
Local binding: label: 24003転送テーブルからも24001が消え、Lo0の3エントリーだけになりました。
RP/0/RP0/CPU0:P1#show mpls forwarding
Sat Sep 12 02:45:18.667 UTC
Local Outgoing Prefix Outgoing Next Hop Bytes
Label Label or ID Interface Switched
------ ----------- ------------------ ------------ --------------- ------------
24000 Pop 4.4.4.4/32 Gi0/0/0/1 10.3.4.4 24167
24002 Pop 2.2.2.2/32 Gi0/0/0/0 10.2.3.2 34825
24003 24003 5.5.5.5/32 Gi0/0/0/1 10.3.4.4 101594 絞っても通信は変わらない
この記事の核心です。CE1からCE2へのtracerouteは、STEP 0とまったく同じラベルスタックを通ります。
RP/0/RP0/CPU0:CE1#traceroute 192.168.2.1 source 192.168.1.1
Sat Sep 12 02:49:06.719 UTC
Type escape sequence to abort.
Tracing the route to 192.168.2.1
1 10.1.2.2 5 msec 4 msec 4 msec
2 10.2.3.3 [MPLS: Labels 24003/24005 Exp 0] 14 msec 22 msec 14 msec
3 10.3.4.4 [MPLS: Labels 24003/24005 Exp 0] 15 msec 15 msec 16 msec
4 10.4.5.5 [MPLS: Label 24005 Exp 0] 16 msec 15 msec 15 msec
5 10.5.6.6 16 msec * 17 msec トランスポートラベル24003(5.5.5.5/32行き)とVPNラベル24005の2段スタックで、P2でPHPによりトランスポートラベルが外れる、という動きが保たれています。pingも全STEPで無損失でした。
| STEP | LIBのプレフィックス数(P1) | CE1 → CE2のping |
|---|---|---|
| 0 | 7 | 100%(50/50) |
| 1 | 4 | 100%(50/50) |
| 2 | 4 | 100%(50/50) |
| 3 | 4 | 100%(50/50) |
| 4 | 7 | 100%(50/50) |
ラベルを4割減らしても、転送は1パケットも落ちません。
STEP 2:配るときに止める(label advertise)
P1がPE1にだけ配る中身を5.5.5.5/32に絞ります。P2向けは触りません。
ipv4 access-list LDP-PE2-ONLY
10 permit ipv4 host 5.5.5.5 any
!
mpls ldp
address-family ipv4
label
local
advertise
to 2.2.2.2:0 for LDP-PE2-ONLY同じP1を相手にしていても、PE1が受け取るラベルは1本、P2は4本のままです。Labelsの列にそれが出ます。
RP/0/RP0/CPU0:PE1#show mpls ldp neighbor brief
Sat Sep 12 02:53:32.502 UTC
Peer GR NSR Up Time Discovery Addresses Labels
ipv4 ipv6 ipv4 ipv6 ipv4 ipv6
----------------- -- --- ---------- ---------- ---------- ------------
3.3.3.3:0 N N 00:18:17 1 0 3 0 1 0 RP/0/RP0/CPU0:P2#show mpls ldp neighbor brief
Sat Sep 12 02:52:41.600 UTC
Peer GR NSR Up Time Discovery Addresses Labels
ipv4 ipv6 ipv4 ipv6 ipv4 ipv6
----------------- -- --- ---------- ---------- ---------- ------------
3.3.3.3:0 N N 00:54:50 1 0 3 0 4 0
5.5.5.5:0 N N 00:49:38 1 0 2 0 4 0 設定を入れた瞬間、P1はPE1へLabel Withdrawを3つ送っています。添付のキャプチャーのNo.1832です。
Internet Protocol Version 4, Src: 3.3.3.3, Dst: 2.2.2.2
Label Distribution Protocol
Version: 1
PDU Length: 90
LSR ID: 3.3.3.3
Label Space ID: 0
Message Type: Label Withdrawal Message (0x402)
FEC Element Length: 32
Prefix: 3.3.3.3
Message Type: Label Withdrawal Message (0x402)
FEC Element Length: 32
Prefix: 4.4.4.4
Message Type: Label Withdrawal Message (0x402)
FEC Element Length: 32
Prefix: 2.2.2.2PE1が持たなくなったのは、P1が送るのをやめたからです。
STEP 3:受け取るときに止める(label remote accept)
送信側のフィルタを外し、今度はPE1側で受け取りを絞ります。前述のとおりフィルタを外しただけでは取り下げたラベルが戻らないので、clear mpls ldp neighbor 2.2.2.2でセッションを張り直してから投入しています。
ipv4 access-list LDP-PE2-ONLY
10 permit ipv4 host 5.5.5.5 any
!
mpls ldp
address-family ipv4
label
remote
accept
from 3.3.3.3:0 for LDP-PE2-ONLYPE1から見た結果は、STEP 2と区別が付きません。Labelsはやはり1です。
RP/0/RP0/CPU0:PE1#show mpls ldp neighbor brief
Sat Sep 12 03:02:00.308 UTC
Peer GR NSR Up Time Discovery Addresses Labels
ipv4 ipv6 ipv4 ipv6 ipv4 ipv6
----------------- -- --- ---------- ---------- ---------- ------------
3.3.3.3:0 N N 00:04:00 1 0 3 0 1 0 違いが出るのは線路の上です。P1は4本すべてのLabel Mappingを送っています。添付のキャプチャーのNo.2867です。
Internet Protocol Version 4, Src: 3.3.3.3, Dst: 2.2.2.2
Label Distribution Protocol
Version: 1
PDU Length: 118
LSR ID: 3.3.3.3
Label Space ID: 0
Message Type: Label Mapping Message (0x400)
FEC Element Length: 32
Prefix: 3.3.3.3
Message Type: Label Mapping Message (0x400)
FEC Element Length: 32
Prefix: 4.4.4.4
Message Type: Label Mapping Message (0x400)
FEC Element Length: 32
Prefix: 2.2.2.2
Message Type: Label Mapping Message (0x400)
FEC Element Length: 32
Prefix: 5.5.5.52.2.2.2 / 3.3.3.3 / 4.4.4.4のマッピングは届いていますが、PE1はアクセスリストに一致しないので捨てています。showの数字は同じでも、帯域とメッセージ処理は節約できていません。 相手の設定を変えられる立場ならadvertise側で止めるほうが有利です。
| どちらで止めるか | LDPメッセージ | 使いどころ |
|---|---|---|
advertise(送信側) |
流れない | 自分が広告する側を管理できるとき |
remote accept(受信側) |
流れる(捨てるだけ) | 相手の設定に期待できないとき、受ける側だけで決めたいとき |
STEP 4:撤去して元に戻る
すべてのアクセスリストとフィルタを外すと、LIBは7本に戻ります。撤去時はPE1がLabel Requestを送り、P1が7本のLabel Mappingを返しています(キャプチャーのNo.3745とNo.3755)。
RP/0/RP0/CPU0:P1#show mpls ldp bindings summary
Sat Sep 12 03:07:12.304 UTC
LIB Summary:
Total Prefix : 7
Revision No : Current:38, Advertised:38
Local Bindings : 7
NULL : 3 (implicit:3, explicit:0)
Non-NULL: 4 (lowest:24000, highest:24003)
Remote Bindings: 14最終STEPのrunning-configは、ラボの起動時Configと1行も違いません。
設計上の注意
- 絞る基準はBGPのネクストホップです。PEのLoopbackに加えて、RRやインターAS向けに他のPEから参照されるアドレスがあれば、それもアクセスリストに含めます。漏らすとそのPE宛のLSPだけが張れず、VPNが片方向で落ちます
allocateはLIBを小さくしますが、自分が経路を知らなくなるわけではありません。show mpls ldp bindings summaryのTotal Prefixは絞る前の本数のまま(N unresolved)と表示され、ラベルを作っていないプレフィックスも把握されています- フィルタを緩めた変更は、セッションを張り直すまで反映されません(前述)。メンテナンス手順に
clear mpls ldp neighborを含めておきます
検証Configおよびshow結果
各STEPで6台すべてから、次の種類をルータごとに分けて取得しています。検証Configはこの..._run.txtです(最終状態は最後のSTEPのもの)。
| ファイル | 内容 |
|---|---|
..._show.txt |
show version / show interface description / show mpls ldp bindings 一式 / show mpls forwarding など |
..._log.txt |
そのSTEPの範囲だけに絞ったshow logging。各STEPの開始時にlogmsgでマーカーを入れ、その時刻をshow logging startに指定して取得したもの |
..._run.txt |
そのSTEP時点のshow running-config(=そのSTEPの検証Config) |
..._ping.txt |
そのSTEPのping(50発、timeout 1秒)とtraceroute |
..._trace.txt |
show mpls ldp trace binding / peer / discovery など(コア4台のみ) |
..._commit.cfg |
そのSTEPで実際にcommitした設定だけ。 設定を変えたルータの分のみ |
STEP 0:初期状態
| ルータ | show出力 | syslog | running-config | ping | trace | commit |
|---|---|---|---|---|---|---|
| CE1 | show | log | run | ping | - | - |
| PE1 | show | log | run | ping | trace | - |
| P1 | show | log | run | ping | trace | - |
| P2 | show | log | run | ping | trace | - |
| PE2 | show | log | run | ping | trace | - |
| CE2 | show | log | run | ping | - | - |
STEP 1:label allocateで/32だけに絞る(コア4台)
| ルータ | show出力 | syslog | running-config | ping | trace | commit |
|---|---|---|---|---|---|---|
| CE1 | show | log | run | ping | - | - |
| PE1 | show | log | run | ping | trace | cfg |
| P1 | show | log | run | ping | trace | cfg |
| P2 | show | log | run | ping | trace | cfg |
| PE2 | show | log | run | ping | trace | cfg |
| CE2 | show | log | run | ping | - | - |
STEP 2:label advertiseでPE1へ配る中身だけ絞る
| ルータ | show出力 | syslog | running-config | ping | trace | commit |
|---|---|---|---|---|---|---|
| CE1 | show | log | run | ping | - | - |
| PE1 | show | log | run | ping | trace | - |
| P1 | show | log | run | ping | trace | cfg |
| P2 | show | log | run | ping | trace | - |
| PE2 | show | log | run | ping | trace | - |
| CE2 | show | log | run | ping | - | - |
STEP 3:送信側を外しlabel remote acceptで受信側を絞る
| ルータ | show出力 | syslog | running-config | ping | trace | commit |
|---|---|---|---|---|---|---|
| CE1 | show | log | run | ping | - | - |
| PE1 | show | log | run | ping | trace | cfg |
| P1 | show | log | run | ping | trace | cfg |
| P2 | show | log | run | ping | trace | - |
| PE2 | show | log | run | ping | trace | - |
| CE2 | show | log | run | ping | - | - |
STEP 4:すべて撤去(最終状態)
| ルータ | show出力 | syslog | running-config | ping | trace | commit |
|---|---|---|---|---|---|---|
| CE1 | show | log | run | ping | - | - |
| PE1 | show | log | run | ping | trace | cfg |
| P1 | show | log | run | ping | trace | cfg |
| P2 | show | log | run | ping | trace | cfg |
| PE2 | show | log | run | ping | trace | cfg |
| CE2 | show | log | run | ping | - | - |
PE1 - P1間のキャプチャー全体です。STEP 1のLabel Withdrawから、STEP 4でラベルが戻るまでが1本に入っています。
PE1 - P1間のキャプチャー全体をダウンロード参考
| 出典 | 参照した箇所 |
|---|---|
| RFC 5036 LDP Specification | 2.6.3節(Downstream Unsolicited / on Demand)。ラベル広告のフィルタはRFCに規定が無いことの確認 |
| IOS XR MPLS Configuration Guide | label allocate / label advertise / label remote acceptの構文 |
検証はXRd 26.1.1(Cisco Modeling Labs)で実施しました。