COGNITIVE

Networking

JunosでIX BGP Route Serverを作る

概要

Junos 17.4からBGP Route Serverの機能が実装されました。
最近プライベートな活動でもIXを立ち上げようとしているので触ってみました。

BGP Route Serverとは

通信事業者が相互接続してトラフィック交換をする手段の一つに、Internet eXhange(IX)があります。
IXに接続するとこでトランジット事業者への依存度を下げ、コスト削減や効率的なトラフィックコントロールができる場合があります。
IXに接続した事業者はそこで経路情報の交換を行いトラフィックを流しますが、IXの接続には大きく分けて2種類の方式(Peering)があります。

  • Bilateral Peering
    • IX上で特定の相手と一対一で接続する
    • 各事業者との個別の接続交渉が必要
  • Multilateral Peering
    • Multi-Lateral Peering Agreement(MPLA)に同意した事業者とRoute Serverとの接続を介して経路情報を交換する
    • 個別の接続交渉や設定などが不要で複数の事業者とpeerしているように見える
    • Bilateralと比較してトラフィックコントロールが難しい

IXには昔から接続ユーザのトラフィック交換に干渉すべきではないという考え方があり、通常はL2セグメントを介しての接続になります。Multilateral PeeringはRoute ServerとBGP peerを張って接続するので、Control PlaneはL3接続になります。

Route Serverに必要な機能

Route Serverにはその特性故に、必須の機能がいくつかあります。
IXは複数の事業者が相互接続するので、eBGP接続になりますが、通常のeBGPの動作(RFC4271)では実現できない機能があります。

BGP Attributeの透過

先述のように、IXはユーザのトラフィック交換に干渉しないという考え方と、Route Server自体の負荷を軽減するために、Data Planeを流れるユーザトラフィックはRoute Serverを経由しないようにする必要があります。
BGPのTCP 179番ポートでやり取りされるControl Planeの通信のみRoute Serverを経由し、それ以外の通信はIXのL2セグメント上でダイレクトに交換されるようにします。

これを実現するにはRoute ServerはRoute Server ClientからのUPDATEメッセージをすべて受け入れ、いくつかのBGPの経路情報に付いた属性をそのまま透過しなければなりません。

  • NEXT_HOP
    • Route ServerはRoute Server Clientが広報した経路のNEXT_HOPを変更せずに他のClientに送信します
    • 通常eBGPはNEXT_HOPを自身のアドレスに書き換え(NEXT_HOP_SELF)をしますがRoute Serverはこれを行いません
    • これによりData PlaneがRoute Serverを経由することなく、直接IXのL2セグメント上でトラフィック交換が可能になります
  • MED
    • Route Serverは転送プロセスには不干渉のためMED値を変更しません
  • AS-PATH
    • Route Serverは経路情報をclientに伝搬させる時にAS-PATHに自身のAS番号を付加しません
    • Route Server Clientから見ると、Route Serverから受信した経路のAS-PATH情報にはRoute ServerのAS番号が付いてい無いので、経路情報的には直接相手から貰ったように見えます。
    • これはルータのデフォルト動作だと不正なAS-PATHと判定されることがあるので、Route Serverと接続するClient Routerで隣接ASから受信した経路のAS-PATHの先頭にそのASが無い場合に当該経路を弾くvalidationを無効にしなければならないこともあります
  • Community
    • DDoS対策などIXがローカルで定義している特殊用途のcommunityを除いて、Route Serverはcomminity値の変更、処理、または削除をしません

上記のいくつかはRFC4271違反の動作でしたが、2016年にRoute Serverの仕様について規定したRFC7947と、そのオペレーションについてRFC7948が策定されました。

BGP Path Hidingの防止

BGP環境をスケールさせる上で時々課題になるのが、ベストパス選択の問題です。  
f:id:cognify:20180108113026p:plain
通常のBGPの経路処理プロセス
https://frrouting.org/user-guide/Description-of-the-Route-Server-model.html
 
上の図はQuagga(FRR)の実装を例に取った非Route Server環境(Bilateral Peer)でのBGPの経路処理プロセスを表しています。

各peerから受信した経路がadj-RIB-in Tableに格納後、import filterを通過しBGP Table(Loc-RIB)でベストパスが選択されグローバルルーティングテーブルにインストール、out filter適用後に各peerに送信されます。

Route Server ClientからRoute Serverに同じ経路が広報されると、Route Serverは接続されているすべてのClientに伝播するための単一のパスを選択します。
これが時々問題になることがあります。

また、IXにはユーザが特定のメンバとの経路交換をしないようにRoute Serverへフィルタを設定できるようになっていることがあります。 たとえば複数のRoute Server Clientが同一の経路をRoute Serverへ広報した場合、特定のRoute Server Clientへのベストパスをフィルタ処理するようにRoute Serverが設定されている場合、そのRoute Server Clientはその経路へのパスを受け取りません。 しかしRoute Serverの単一のルーティングテーブルで計算したベストパスが、このフィルタされたパスに向いている場合、Route Server Clientは当該経路が見えない状態になってしまうことがあります。

f:id:cognify:20180108123657p:plain
http://ripe61.ripe.net/presentations/260-ripe61-draft-jasinska.pdf

このように各Route Server Clientから受信した経路をすべて同一のRIBに載せてしまうと問題が発生します。
これをBGP Path Hidingといいます。

このような事象を防ぐためのいくつかの方法があります。
最も一般的な方法が、 Multi Client RIB Proccess で各peer毎にRouting Tableを管理し、独立したベストパス選択を実施する方法です。

f:id:cognify:20180108113545p:plain
Multi Client RIBのBGPのプロセス
https://frrouting.org/user-guide/Description-of-the-Route-Server-model.html

上の図はBilateral PeerとMultilateral Peerの混在環境でのBGPの経路広報プロセスについて表したものです。
非Route Server環境との違いは、Route ServerはClientに代わってベストパスの選択を行う必要があることです。

Multi Client RIBの他にもADD-PATHなどを用いて経路の選択肢を増やすなどのやり方もありますが、長くなるので割愛します。

また、IXによってはCommunityやIRR情報を用いて特定のメンバにのみ経路を広報しないという動作(Selective Announcement)をさせることも可能ですが、これもPath Hidingの原因になりますので注意が必要です。

Route Serverに利用されるBGP実装

今回試すようにJunosのようなルータでもRoute Serverとして動作させることは可能ですが、世界的にはAPIの利用や拡張性の高さ、運用の効率化の観点からRoute ServerはLinux上でBGPデーモンを動かして利用することが一般的です。

Route Serverの実装は以下のようなものがあります。

  • BIRD
    • 世界的に広く利用されているルーティングデーモンで、Route ServerとしてのシェアはEU方面を中心に圧倒的です
  • Quagga(FRR)
    • こちらも広く利用されているルーティングデーモンですが、海外のIX Route Serverにはパッチを当てた特殊仕様のQuaggaが利用されています
  • GoBGP
    • NTTとJPNAPが共同で開発したBGPに特化したルーティングデーモンでその名の通りGoによる実装です
    • quaggaやBIRDではフィルタ更新に時間がかかりCLIの応答がしばらくなくなるなどのパフォーマンス上の問題があったため、マルチコア化などで近年のIXの運用レベルまでスケール出来るように設計されています
    • JPNAPでは商用導入されています
  • OpenBGPD
  • Cisco
  • Junos
    • Junos 17.4からRoute Serverとしての基本機能が実装されました

Junos でのRoute Serverの設定

Linuxでやったほうが手っ取り早いのですが、今回はJunosで試してみます。
Route ServerとしてJunos 17.4R1.16を利用します。

構成は以下の通りです。

f:id:cognify:20180108135316p:plain

Route Server Clientは自身のprefixを広報します。

JunosをRoute Serverにする

JunosをRouter Serverとして動作させるのはFRR(Quagga)と同様で簡単です。
通常のBGP設定に加えてBGPネイバーに対してroute-server-clientの設定を入れるだけでRoute Server機能を有効化できます。

root@RouteServer> show configuration protocols bgp
group RSC1 {
    type external;
    route-server-client;
    family inet {
        unicast;
    }
    peer-as 4200000001;
    neighbor 192.168.100.11;
}
group RSC2 {
    type external;
    route-server-client;
    family inet {
        unicast;
    }
    peer-as 4200000002;
    neighbor 192.168.100.12;
}

Clinet1 / Client2 の状態確認をします。

root@lab_vMX> show bgp summary logical-system RSC1
Groups: 1 Peers: 1 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       1          1          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.168.100.1    4200000000        279        278       0       0     2:04:20 1/1/1/0              0/0/0/0
root@lab_vMX> show route logical-system RSC1 protocol bgp

inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

192.168.202.0/24   *[BGP/170] 01:43:36, localpref 100, from 192.168.100.1
                      AS path: 4200000002 I, validation-state: unverified
                    > to 192.168.100.12 via ge-1/0/0.0
root@lab_vMX> show bgp summary logical-system RSC2
Groups: 1 Peers: 1 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
inet.0
                       1          1          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
192.168.100.1    4200000000        272        271       0       0     2:00:50 1/1/1/0              0/0/0/0
root@lab_vMX> show route logical-system RSC2 protocol bgp

inet.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

192.168.201.0/24   *[BGP/170] 01:45:19, localpref 100, from 192.168.100.1
                      AS path: 4200000001 I, validation-state: unverified
                    > to 192.168.100.11 via ge-1/0/1.0

それぞれのClinetで受信した経路を確認すると、Route ServerのAS番号がAS pathに付いていないことと、Next-hopが直接対向のClientになっていることでControl PlaneとData Planeが分離されていることが確認できます。 これでは各Clientは直接BGPピアを確立することなく、直接経路を交換した状態と同様の状態になりました。

まとめ

Route Serverの最低限の動作確認しかしていませんが、実際のIXではRoute ServerだけでなくSwitch Fabricの部分まで含めて細かい設定やチューニングが必要になります。
今回はJunosでRoute Serverを作りましたが、実環境で導入する際には運用の効率化や自動化の観点からLinux上でGoBGPのようなBGPデーモンを利用するほうが手軽だと感じています。 BGPコンテナを利用した検証環境の構築も手軽にできるのがメリットです。
また実環境ではIX上のRoute Serverは冗長構成で複数台あることが普通なので、異なるルーティングソフトウェアを利用して構築してあることもあるようです。
最近のIXにはDDoS対策として Black hole community(65535:666)を用いたRTBHや、VLANを用いた特定ユーザグループでのマルチクラウド(Azure, AWS ..etc)/トランジット接続の提供、CDNのコンテンツキャッシュアクセスへの提供など、帯域の効率的利用やポート単価などの時代の変遷に合わせた付加価値サービスも提供しています。
細かい技術要素を検証するのも楽しいですが今回はここまでにします。

FRR v3.0でRFC8203 - BGP Administrative Shutdown Communication を試したメモ

仕事柄ルーティングソフトウェアにFRRを使うことがよくあり、先日version3.0.2 がリリースされたので、マージされた新機能の一つを試してみました。
15分でできるとても簡単な内容です。

RFC8203について

RFC8203 はBGPのpeerを明示的に閉塞する時に、neighborに対してNOTIFICATIONで任意のメッセージ(文字列)を通知できる機能です。
イケてない運用現場では突然深夜にpeerが落ちて問い合わせをしたら、メンテナンスで事前の通知を見逃していたor忘れていただけだったということが発生することがあります。
メンテナンスなどでpeerをadmin shutdownするのに合わせて、事前通知したチケットやMLの番号がメッセージと一緒に書かれていると、不毛なメール問い合わせを減らせるかもしれません。

メッセージのエンコード規定は以下です。

   0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Error Code 6  |    Subcode    |    Length     |     ...       \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               /
   \                                                               \
   /                 ... Shutdown Communication ...                /
   \                                                               \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

文字列はUTF-8エンコードされる必要があります。
使用例:

"[TICKET-1-1438367390] software upgrade; back in 2 hours"

FRRの設定

FRR はQuaggaからforkしたUnixおよびLinuxプラットフォームで動作するIPルーティングプロトコルスイート(ルーティングデーモン)のprojectで、Linux Foundationが管轄しています。
主にDCでの利用を想定したRFC5549 BGP Unnumberedや基本的なMPLS、EVPNを実装しており、Cumulus Linuxも最近のバージョンからルーティングのコアコンポーネントをFRRに変更しています。

構成

Vagrant upしたUbuntu 16.04を2台接続します。諸事情でカーネルを4.10にしています。

+---------------+
| Ubuntu1 16.04 |
|   FRR v3.0    |
+---------------+
        |
      eBGP
  172.168.0.0/30
        |
+---------------+
| Ubuntu2 16.04 |
|   FRR v3.0    |
+---------------+
# uname -a
Linux ubuntu1 4.10.0-42-generic #46~16.04.1-Ubuntu SMP Mon Dec 4 15:57:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

BGPの設定

ただShutdown Communicationで遊びたいだけなので経路広報はせずにpeerを張る設定だけします

!ubuntu1
router bgp 4200000001
 neighbor 172.168.0.2 remote-as external
!
!ubuntu2
router bgp 4200000002
 neighbor 172.168.0.1 remote-as external
!
ubuntu1# sh ip bgp sum

IPv4 Unicast Summary:
BGP router identifier 10.0.0.1, local AS number 4200000001 vrf-id 0
BGP table version 0
RIB entries 0, using 0 bytes of memory
Peers 1, using 21 KiB of memory

Neighbor        V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd
172.168.0.2     4 4200000002     322     380        0    0    0 00:00:14            0
ubuntu2# sh ip bgp sum

IPv4 Unicast Summary:
BGP router identifier 10.0.0.2, local AS number 4200000002 vrf-id 0
BGP table version 0
RIB entries 0, using 0 bytes of memory
Peers 1, using 21 KiB of memory

Neighbor        V         AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd
172.168.0.1     4 4200000001     283     532        0    0    0 00:01:11            0

Total number of neighbors 1

BGPのdebugを有効にし、イベントをログに吐かせます。

!
debug bgp neighbor-events
log file /var/log/frr/frr.log
!

Shutdown Communication

  • 送信側
    ネット中立性も廃止されたし、もうお前とpeerはしないという世界を想定して以下のようなメッセージを送ります。
    We'll shut down the peering session with you because net neutrality was abolished.
ubuntu1(config-router)# neighbor 172.168.0.2 shutdown message We'll shut down the peering session with you because net neutrality was abolished.
  • 受信側
    Error Code 6 , Subcode 2("Administrative Shutdown")で送信側のメッセージがlogに表示されています(1行目)
2017/12/17 10:07:18 BGP: %NOTIFICATION: received from neighbor 172.168.0.1 6/2 (Cease/Administratively Shutdown) "We'll shut down the peering session with you because net neutrality was abolished."
2017/12/17 10:07:18 BGP: 172.168.0.1 [FSM] Receive_NOTIFICATION_message (Established->Clearing), fd 10
2017/12/17 10:07:18 BGP: 172.168.0.1 went from Established to Clearing
2017/12/17 10:07:18 BGP: 172.168.0.1 [FSM] Clearing_Completed (Clearing->Idle), fd -1
2017/12/17 10:07:18 BGP: 172.168.0.1 went from Clearing to Idle
2017/12/17 10:07:20 BGP: 172.168.0.1 [FSM] Timer (start timer expire).
2017/12/17 10:07:20 BGP: 172.168.0.1 [FSM] BGP_Start (Idle->Connect), fd -1
2017/12/17 10:07:20 BGP: 172.168.0.1 [Event] Connect start to 172.168.0.1 fd 10
2017/12/17 10:07:20 BGP: 172.168.0.1 [FSM] Non blocking connect waiting result, fd 10
2017/12/17 10:07:20 BGP: 172.168.0.1 went from Idle to Connect
2017/12/17 10:07:20 BGP: 172.168.0.1 [FSM] TCP_connection_open (Connect->OpenSent), fd 10
2017/12/17 10:07:20 BGP: 172.168.0.1 open active, local address 172.168.0.2
2017/12/17 10:07:20 BGP: 172.168.0.1 Sending hostname cap with hn = ubuntu2, dn = (none)
2017/12/17 10:07:20 BGP: 172.168.0.1 sending OPEN, version 4, my as 4200000002, holdtime 180, id 10.0.0.2
2017/12/17 10:07:20 BGP: 172.168.0.1 went from Connect to OpenSent
2017/12/17 10:07:20 BGP: 172.168.0.1 [Event] BGP connection closed fd 10
2017/12/17 10:07:20 BGP: 172.168.0.1 [FSM] TCP_connection_closed (OpenSent->Active), fd 10
2017/12/17 10:07:20 BGP: 172.168.0.1 went from OpenSent to Active

以上です。簡単です。

まとめ

直接相手に言いにくい本音をBGPで伝えることができる、コミュ障エンジニアにとって優しい機能です(^^)

RFC8203はBIRD v2.0でも利用できるようになっています。
予めメッセージの内容を定義しておき、受信したメッセージに合わせて任意のイベントを走らせるようなことも実装次第でできそうです。

半年ぶりのブログ更新でリハビリにゆるーい内容を書きました。。

Junosで始めるMPLS入門 その3 LDP over RSVP VPN編

前回の記事でRSVPシグナリングと、障害発生時にバックアップのLSPに高速で切り替えるLocal Repair(Fast ReRouteの一種)の動作を確認しました。
今回はLDPを使ったネットワークの動作を確認していきたいと思いますが、RSVPより機能の少ないLDPでただラベルを配布しても面白くないので、前回利用したRSVPネットワークの上にLDPをトンネリングして通し、離れた拠点同士をVPN接続します。
LDP over RSVPと呼ばれる、昔からよくMPLSコアネットワークで使われたLDPのスケーリング手法の一つです。
これによりRSVPのメリットを享受しつつLDPのオペレーションをスケールさせる、利便性の高い?MPLSネットワークを作ることができます。
今回からIPパケットにラベルをスタックする動作が加わります。
また、L3VPNを動かすにあたってMP-BGPというBGPを拡張したVPNラベルのシグナリングを行うので事前知識が若干必要になります。
MPLSとBGPを使ったVPN技術については以下の資料に基礎的な概要が記載されています。
MPLS-VPN 基礎

検証手順

今回は、以下の順に設定を実施していきます。

  1. 新たにPEとCEを既存構成に接続
  2. PEとPでLDP neighborを確立
  3. Pルータ間でLDP Tunnelを確立
  4. PE同士でMP-iBGP接続
  5. PEにCEをBGPで接続、経路交換

大まかな流れは以上です。

構成

今回使用する構成は最終的に以下のようになります。
f:id:cognify:20170509084159p:plain
前回までの構成にエッジルータ(PE)と顧客ルータ(CE)を新たに2台ずつ接続します。

IP-VPNなどに馴染みのある人は知っていると思いますが、MPLS-VPNでは以下の用語を使います。

  • P(Provider Router)
    • MPLSドメインのコアとなるLSR
    • 網内転送用の最上部のラベルのみ参照し転送する
  • PE(Provider Edge Router)
    • MPLSドメインのエッジとなるLER
    • Pと複数のCEと接続する
    • CEの経路をVRF毎に管理し、識別用のラベルをPush,さらに網内転送用のラベルをPushしてPに転送する
  • CE(Customer Edge Router)
    • 非MPLSドメインのルータ
    • 何らかの方法でPEと接続する

上記の構成では、RSVPドメインのルータ(各拠点)がPになります。

LDP Tunnelingの設定

PEルータが接続されたPルータ間でLDP Tunnelingを有効にすることで、直接接続されていないPE間でLDPのパケットのやり取りが行えるようになります。
パケットヘッダがラベルになっただけで、通常のIPパケットをencap/decapするVPNと同じイメージです。

LDPの有効化

LDPドメインとなるPとPEのインターフェースでLDPを有効にします。

oot@lab-vmx01# show | compare
[edit logical-systems Fukuoka protocols]
+    ldp {
+        interface all;
+    }
[edit logical-systems Nagoya protocols]
+    ldp {
+        interface all;
+    }
[edit logical-systems Shinagawa protocols]
+    ldp {
+        interface all;
+    }
[edit logical-systems Toyosu protocols]
+    ldp {
+        interface all;
+    }

P - PE間でLDP sessionが確立されます。

root@lab-vmx01:PE1> show ldp neighbor
Address            Interface          Label space ID         Hold time
10.0.0.28          lt-0/0/0.29        10.255.255.8:0           14
10.0.0.30          lt-0/0/0.31        10.255.255.9:0           14

root@lab-vmx01:PE2> show ldp neighbor
Address            Interface          Label space ID         Hold time
10.0.0.34          lt-0/0/0.35        10.255.255.6:0           12
10.0.0.36          lt-0/0/0.37        10.255.255.7:0           11

root@lab-vmx01> show ldp session logical-system PE1
  Address           State        Connection     Hold time  Adv. Mode
10.255.255.8        Connecting   Opening          0          DU
10.255.255.9        Connecting   Opening          0          DU

root@lab-vmx01> show ldp session logical-system PE2
  Address           State        Connection     Hold time  Adv. Mode
10.255.255.6        Connecting   Opening          0          DU
10.255.255.7        Connecting   Opening          0          DU

PルータでのLDP Tunneling

前回の記事で、Pルータである Nagoya - Shinagawa 間でRSVPでLSPを作成しました。
このパスをそのまま利用してNagoyaとShinagawaでLDPをトンネリングします。

root@lab-vmx01> show configuration logical-systems Nagoya protocols mpls label-switched-path Shinagawa
to 10.255.255.7;
ldp-tunneling;
no-cspf;
primary to_Shinagawa_ACT;
secondary to_Shinagawa_STBY;

LDP Tunneling時のラベルスタック

LDP over RSVP設定時の動作を細かく見ていきます。

LDPをトンネリングしているPルータ(Nagoya-Shinagawa)間の経路を見てみます。
前回の記事で設定したRSVPのstrict pathにLDPが従っていることがわかります。

root@lab-vmx01:PE1> traceroute mpls ldp 10.255.255.11
  Probe options: ttl 64, retries 3, wait 10, paths 16, exp 7, fanout 16

  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    1   299856  LDP         10.0.0.28        (null)           Success
  FEC-Stack-Sent: LDP FEC-Change-Recieved: PUSH-RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    2   299920  RSVP-TE     10.0.0.22        10.0.0.28        Success
  FEC-Stack-Sent: RSVP,LDP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    3   299856  RSVP-TE     10.0.0.0         10.0.0.22        Success
  FEC-Stack-Sent: RSVP,LDP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    4   299920  RSVP-TE     10.0.0.3         10.0.0.0         Success
  FEC-Stack-Sent: RSVP,LDP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    5   299888  RSVP-TE     10.0.0.15        10.0.0.3         Success
  FEC-Stack-Sent: RSVP,LDP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    6        3  RSVP-TE     10.0.0.19        10.0.0.15        Egress
  FEC-Stack-Sent: RSVP,LDP FEC-Change-Recieved: POP-RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    6        3  RSVP-TE     10.0.0.19        10.0.0.15        Success
  FEC-Stack-Sent: LDP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    7        3  LDP         10.0.0.37        10.0.0.19        Egress
  FEC-Stack-Sent: LDP

  Path 1 via lt-0/0/0.29 destination 127.0.0.64

上記の結果を詳しく見ていくと、いくつか重要なポイントがあります。
trace結果の前半と後半で、以下の記述があります。

  • FEC-Stack-Sent: LDP FEC-Change-Recieved: PUSH-RSVP
  • FEC-Stack-Sent: RSVP,LDP FEC-Change-Recieved: POP-RSVP

これが、LDPラベルの上にRSVPラベルをPushしている動作と、Popしている動作です。
RSVP区間ではラベルが何度もSwapされますが、下層のLDPラベルはSwapもPopもされません。
最後のRSVP Egress LSR(10.0.0.19)でRSVPラベルがPopされ、LDPラベルがtopとなった状態で転送されLDPのEgress LSR(10.0.0.37)に到達するとLDPラベルもPopされIPパケットで転送されます。

IGPトラフィックのLSP転送

IGPトラフィックをLSPでフォワーディングさせるために、いくつか設定が必要です。

root@lab-vmx01> show configuration logical-systems PE1 protocols mpls
traffic-engineering {
    mpls-forwarding;
}
interface all;

このオプションを使わないで対向のPE2宛に traceroute を実行するとどうなるでしょうか?
実際にやってみます。

root@lab-vmx01:PE1> traceroute  10.255.255.11
traceroute to 10.255.255.11 (10.255.255.11), 30 hops max, 48 byte packets
 1  10.0.0.28 (10.0.0.28)  0.644 ms  0.506 ms  0.425 ms
 2  10.0.0.22 (10.0.0.22)  0.427 ms  0.412 ms  0.393 ms
     MPLS Label=299920 CoS=0 TTL=1 S=1
 3  10.0.0.0 (10.0.0.0)  0.374 ms  0.468 ms  0.377 ms
     MPLS Label=299856 CoS=0 TTL=1 S=1
 4  10.0.0.3 (10.0.0.3)  0.400 ms  0.418 ms  0.384 ms
     MPLS Label=299920 CoS=0 TTL=1 S=1
 5  10.0.0.15 (10.0.0.15)  0.402 ms  0.436 ms  0.353 ms
     MPLS Label=299888 CoS=0 TTL=1 S=1
 6  10.0.0.19 (10.0.0.19)  0.292 ms  0.298 ms  0.300 ms
 7  10.255.255.11 (10.255.255.11)  0.434 ms  0.657 ms  0.471 ms

最初のホップにラベルがついていません。
つまりLDPの区間にラベルが付かずに転送されてしまったことになります。
その後はRSVPラベルがちゃんとついていますが、なぜこうなったのでしょうか。

IGPのトラフィックがLSPを経由できていない からです。

LDPとRSVPのLSPネクストホップの情報はinet.3というテーブルに格納されます。
このテーブルを再帰解決に使用できるプロトコルはBGPだけというのがJunosのデフォルトの仕様です。
このままではIGPのトラフィックがLSPで転送できません。

この問題を解決するために、Junosにはいくつかオプションが用意されています。

  • traffic-engineering bgp-igp
    • Egress LSR宛のBGPとIGPトラフィックを転送するのにLSPを使用するようにします
    • inet.3 tableの経路がすべてinet.0 tableに移動され、inet.3は使用できなくなります
  • traffic-engineering bgp-igp-both-ribs
    • bgp-igpとほとんど同じですが、inet.3 tableにも経路が残ります
  • traffic-engineering mpls-forwarding
    • RSVP/LDPの経路をフォワーディングにのみ使用します

今回はmpls-forwardingを使用してみます。

root@lab-vmx01# show | compare
[edit logical-systems PE1 protocols mpls]
+     traffic-engineering {
+         mpls-forwarding;
+     }
[edit logical-systems PE2 protocols mpls]
+     traffic-engineering {
+         mpls-forwarding;
+     }

再度traceしてみます。

root@lab-vmx01:PE1> traceroute  10.255.255.11
traceroute to 10.255.255.11 (10.255.255.11), 30 hops max, 48 byte packets
 1  10.0.0.28 (10.0.0.28)  0.896 ms  0.482 ms  0.390 ms
     MPLS Label=299856 CoS=0 TTL=1 S=1
 2  10.0.0.22 (10.0.0.22)  0.383 ms  0.401 ms  0.367 ms
     MPLS Label=299920 CoS=0 TTL=1 S=0
     MPLS Label=299824 CoS=0 TTL=1 S=1
 3  10.0.0.0 (10.0.0.0)  0.368 ms  0.379 ms  0.360 ms
     MPLS Label=299856 CoS=0 TTL=1 S=0
     MPLS Label=299824 CoS=0 TTL=2 S=1
 4  10.0.0.3 (10.0.0.3)  0.409 ms  0.382 ms  0.368 ms
     MPLS Label=299920 CoS=0 TTL=1 S=0
     MPLS Label=299824 CoS=0 TTL=3 S=1
 5  10.0.0.15 (10.0.0.15)  0.434 ms  0.395 ms  0.362 ms
     MPLS Label=299888 CoS=0 TTL=1 S=0
     MPLS Label=299824 CoS=0 TTL=4 S=1
 6  10.0.0.19 (10.0.0.19)  0.383 ms  0.403 ms  0.377 ms
     MPLS Label=299824 CoS=0 TTL=1 S=1
 7  10.255.255.11 (10.255.255.11)  0.404 ms  0.421 ms  0.421 ms

今度はちゃんと最初のホップでLDPラベルがPushされました。LDPラベルの後にRSVPラベルがスタックされて付いていることが確認できます。
S=1が最下層のLDPラベルです。Label=299824がPE2に到達するまで変更されていないことがわかります。

せっかくなので、inet.0 tableも確認します。

root@lab-vmx01:PE1> show route table inet.0
inet.0: 33 destinations, 36 routes (33 active, 0 holddown, 0 hidden)
@ = Routing Use Only, # = Forwarding Use Only
+ = Active Route, - = Last Active, * = Both

10.255.255.11/32   @[OSPF/10] 00:05:56, metric 5
                    > to 10.0.0.28 via lt-0/0/0.29
                      to 10.0.0.30 via lt-0/0/0.31
                   #[LDP/9] 00:05:56, metric 1
                    > to 10.0.0.28 via lt-0/0/0.29, Push 299856

inet.3 tableからコピーされたLSPの宛先となるホストルートがありますが、経路にあまり見慣れない記号がついているのが確認できます。
@ = Routing Use Only
# = Forwarding Use Only
これがmpls-forwardingオプションを使用した場合の特徴で、フォワーディングにのみLSPを使用します。

詳細な説明は本筋から外れるのでここではしませんが、上記の各オプションの動作の違いは異なるルーティングプロトコルで学習した経路を再配布する場合などに顕著に現れますので、経路の優先度などに注意が必要です。
詳しく知りたい人はJuniperの公式ドキュメントを参考にしてください。

PEのMP-iBGP接続

PE1 - PE2 間でiBGP接続を行うため、BGP-L3VPNの設定をします。

root@lab-vmx01:PE1> show configuration protocols bgp
group PE1-to-PE2 {
    type internal;
    local-address 10.255.255.10;
    family inet-vpn {
        unicast;
    }
    neighbor 10.255.255.11;
}

root@lab-vmx01:PE2> show configuration protocols bgp
group PE2-to-PE1 {
    type internal;
    local-address 10.255.255.11;
    family inet-vpn {
        unicast;
    }
    neighbor 10.255.255.10;
}
root@lab-vmx01:PE1> show bgp summary
Groups: 2 Peers: 2 Down peers: 0
Table          Tot Paths  Act Paths Suppressed    History Damp State    Pending
bgp.l3vpn.0
                       1          1          0          0          0          0
Peer                     AS      InPkt     OutPkt    OutQ   Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
10.255.255.11         59105       1899       1902       0       0    14:14:37 Establ
  bgp.l3vpn.0: 1/1/1/0

bgp.l3vpn.0 tableでのpeerが確立されます。
これによりRSVPドメインのPルータでBGPを有効にすることなく、遠方のPE間でiBGP接続ができました。
大規模なネットワークでは、これをPE間でフルメッシュに行うことで、コアルータがBGPの経路を持たない高速なコンバージェンスが可能なネットワークを作ることができます。
この考え方をBGP Free Coreといいます。

CEとPEのBGP接続

最後に両端のPEとCEをeBGPで接続します。

PEの設定

CEの経路をVRFで管理し、RDという識別子を付けVPNv4 Prefixを生成します。
これにより複数のCEで同一prefixを広報してきてもユニークなものとして扱うことができます。
CEからeBGPで受信した経路を、iBGPで対向のPEに広報します。

root@lab-vmx01:PE1> show configuration routing-instances
VPN-A {
    instance-type vrf;
    interface lt-0/0/0.32;
    route-distinguisher 59105:1;
    vrf-import VPN-A-import;
    vrf-export VPN-A-export;
    protocols {
        bgp {
            group VPN-A-CE1 {
                type external;
                peer-as 65530;
                neighbor 192.168.10.2;
            }
        }
    }
}

root@lab-vmx01:PE1> show configuration policy-options policy-statement VPN-A-import
term a {
    from {
        protocol bgp;
        community VPN-A;
    }
    then accept;
}
term b {
    then reject;
}

root@lab-vmx01:PE1> show configuration policy-options policy-statement VPN-A-export
term a {
    from protocol bgp;
    then {
        community add VPN-A;
        accept;
    }
}
term b {
    then reject;
}

root@lab-vmx01:PE1> show configuration policy-options community VPN-A
members target:59105:00;

CEの設定

root@lab-vmx01:CE1> show configuration 
group CE1-to-PE1 {
    type external;
    export EXPORT-MY-ROUTE;
    neighbor 192.168.10.1 {
        peer-as 59105;
    }
}
routing-options {
    autonomous-system 65530;
}

root@lab-vmx01:CE2> show configuration 
group CE2-to-PE2 {
    type external;
    export EXPORT-MY-ROUTE;
    neighbor 192.168.20.1 {
        peer-as 59105;
    }
}
routing-options {
    autonomous-system 65531;
}

BGP経路確認

対向のCEの経路が受信できていることが確認できます。

root@lab-vmx01:CE1> show route
inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

172.16.20.254/32   *[BGP/170] 02:00:44, localpref 100
                      AS path: 59105 65531 I, validation-state: unverified
                    > to 192.168.10.1 via lt-0/0/0.33

root@lab-vmx01:CE2> show route
inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

172.16.10.254/32   *[BGP/170] 02:01:14, localpref 100
                      AS path: 59105 65530 I, validation-state: unverified
                    > to 192.168.20.1 via lt-0/0/0.39

ラベルの3階層スタック

今回の構成ではラベルが最大3つPushされることになります。
FRR作動時にはRSVPラベルがさらにPushされ4つになります。

+--------------+------------------------+
| RSVP Label   | RSVP区間の網内転送ラベル |
+--------------+------------------------+
| LDP Label    | 宛先のPE(FEC)のラベル   | 
+--------------+------------------------+
| BGP-VRF Label| CEの経路を識別するラベル | 
+--------------+------------------------+
| IP Packet    | ユーザのデータ          |
+--------------+------------------------+

MP-BGP/LDP/RSVP とそれぞれの区間でそのラベルしか操作されないため、途中まで同じ経路(パス)を通る通信でも、内部では論理的に分離された通信が可能です。

まとめ

  • MPLSはラベルをスタックし階層構造を作ることで、顧客ごとに論理的に分離したVPN通信を実現する
  • RSVPには、LSPの冗長やQoS、帯域保証の機能などがある
  • LDP over RSVPを使うことで、PE間でトラフィックエンジニアリングのメリットを享受したLDPシグナリングが可能

実際には複数の顧客のCEがPEに多数接続され、もっと複雑なネットワークになります。
ですが特に難解な技術をつかっているわけではありませんし、一つ一つの設定も簡単だったと思います。
Junosの場合、inet.3/mpls.0の役割や経路・ラベルの参照方法が理解できれば苦労しません。
これらを応用すれば、IPv4のみで構成されたMPLSドメインIPv6通信を通すといったことも可能になります。

入門というタイトルなので扱いませんでしたが、最近ユースケースや課題が議論されている以下のような技術もMPLS関連で後で簡単に記事にしようと思います。

  • Inter-AS Option B/C
  • BGP-LU
  • PCEP
  • EVPN-MPLS(Data Plane)
    etc...

これらは使い方によってはとてもおもしろいことができます。

MPLSとBGPは使い古されたプロトコルですが、現在でもアドレスファミリやTLVの拡張が頻繁に行われ、伝搬できる情報の種類を増やし続けています。
新しい技術に触れることも大切ですが、古くからある基礎に振り返ってみるのも悪くないのではと思いまとめてみました。

おわり

Junosで始めるMPLS入門 その2 RSVP-TE LSP編

前回の記事で、Static LSPによる手動でのラベルパスの設定を行いました。
手動で設定するのは運用上とても面倒なので、今回は動的なラベル配布プロトコルである RSVP-TE を利用した基本動作を確認したいと思います。
表記の簡略化のため、今後RSVP-TEをRSVPと記載しますが同義です。

RSVPとは

RFC読んでください
ラベル配布を行うシグナリングプロトコルの一つです。
ラベル情報のほかに、帯域予約や明示的な経路の設定などが可能でLDPよりも高度な運用が可能です。
現在はラベル配布プロトコルにLDPとRSVPが広く利用されているので、この二つを理解していればMPLSの運用で困ることはないと思います。
※MP-BGPというBGPを拡張したシグナリング方法もありますが、これは後で扱います。

ラベルの配布方法

動的なラベルの配布方法には大きく分けて二つの手順(モード)があります。

  • DU(Downstream Unsolicited)
    • 宛先prefix(FEC)にラベルを割り当て、宛先(下流)のLSRからラベルを配布する方式
    • LDPがこの方式です
    • OSPFなどのIGPの経路情報をラベルにマッピングするのでLSPはIGPの最短経路に依存します
  • DoD(Downstream-on-Demand)
    • 問い合わせに対してラベル情報を返す方式
    • RSVPがこの方式です
    • LSPがIGPの最短パスに依存しない設計が可能です

RSVP Negotiation

LSPをinitiationするHead-End LSR(送信元)からTail-End LSR(宛先)に対してPATHメッセージを送り、ラベル情報を要求します。
このPATHメッセージには以下のオブジェクトが含まれています。

  • Label Request Objetct
    • ラベルの割り当て要求
  • ERO(Explicit Route Object)
    • 宛先までのパス(ネクストホップ)情報の一覧
    • このパス情報を元にPATHメッセージが送信される
  • RRO(Record Route Object)
    • 経由したリンク情報の一覧
  • Session Object
    • LSPの優先度や名前など

PATHメッセージを受信したTail-End LSRは、ラベル割り当てを行い逆方向のRESVメッセージで返答します。
RESVメッセージにはLabel Objectでラベル情報が格納されています。
これをHop-by-Hopで行いLSPが確立します。 詳細はGoogle先生に聞いてください。

余談ですが、かつてラベル配布プロトコルにはTDPやCR-LDPと呼ばれるものがありましたが、某ベンダの資格試験でしか見たことがないためここでは扱いません。 そもそもJunosでは動きません。

RSVP LSPの設定

実際にラボ環境で動かしてみましょう。

構成

NW構成は前回と同じものを使用します。logical-systemの設定も同様です。
今回は Nagoya → Shinagawa 間のパスをRSVPで制御したいと思います。
primary pathとバックアップ用のsecondary pathを作成し、primary pathの障害時に速やかにsecondary pathにカットオーバーできる構成にします。 戻りの経路にもバックアップパスを作成します。

事前準備

前回と同様、ルータでMPLSを有効にする必要があります。

root@lab-vmx01:Nagoya> show configuration protocols mpls
interface all;

RSVPを有効にします。

root@lab-vmx01:Nagoya> show configuration protocols rsvp
interface all;

EROの設定

RSVPのPATHメッセージはEROを元に生成されるので、EROの設定を行います。

EROの作成方法

EROには作り方が二通りあります。
明示的にパスを指定する方法と、CSPFというアルゴリズムで計算されたパスを利用する方法です。

  • Explicit ERO
    • Strict Mode
      • 宛先までの経路を明示的に指定
    • Loose Mode
      • 宛先までの経路をIGPの最短経路で指定
  • Dynamic ERO
    • CSPF
      • 宛先までの経路をCSPFで計算して指定

CSPFについての詳しい説明についてはここでは割愛します。
OSPFで使われているダイクストラアルゴリズムを拡張して、メトリックに加えて利用可能な帯域など、トラフィックエンジニアリング(TE)に必要な情報を伝搬できるようにしたものです。

Explicit EROのモード

CSPFに完全依存しないExplicit EROには以下の二つのモードがあるので、設計によって使い分けます。
二つを組み合わせて使うこともできます。

  • Strict ERO
    • LSPの経路を明示的に指定する方法
    • ここに指定されたネクストホップを必ず通る
  • Loose ERO
    • LSPの経路をIGPの最短経路に委ねる方法
    • ここに指定されたホップまでの経路はIGPの最短経路で到達する

Nagoya → Shinagawa 方向のパス

以下の経路のパスになるようにShinagawa向けのEROを設定します。 ここではCSPFは使わずに、Explict EROで設定をします。
Primary Path:Nagoya → Dojima → Otemachi → Shibuya → Ikebukuro → Shinagawa
Secondary Path:Nagoya → Dojima → [IGP Shortest Path] → Shinagawa

f:id:cognify:20170506104934p:plain

primary pathは完全にstrict指定で到達し、secondary pathではネクストホップのDojimaまでstrictで、その先はOSPFの最短メトリックに任せるlooseに設定にしています。
また、ネクストホップはインターフェースのアドレスを設定しても問題ありませんが、各ルータのloopback addressをOSPFで学習しているのでそれを設定します。

root@lab-vmx01:Nagoya> show configuration protocols mpls
label-switched-path Shinagawa {
    to 10.255.255.7;
    no-cspf;
    primary to_Shinagawa_ACT;
    secondary to_Shinagawa_STBY;
}
path to_Shinagawa_ACT {
    10.255.255.2 strict;
    10.255.255.1 strict;
    10.255.255.3 strict;
    10.255.255.5 strict;
    10.0.0.19 strict;
}
path to_Shinagawa_STBY {
    10.255.255.2 strict;
    10.0.0.21 loose;
}
interface all;

Shinagawa → Nagoya 方向のパス

以下の経路のパスになるようにShinagawa向けのEROを設定します。
Primary Path:Shinagawa → Ikebukuro → [IGP Shortest Path] → Nagoya
Secondary Path:Shinagawa → [IGP Shortest Path] → Nagoya

f:id:cognify:20170506104919p:plain

こちらのパスは殆どがIGPに依存しています。

root@lab-vmx01:Shinagawa> show configuration protocols mpls
label-switched-path Nagoya {
    to 10.255.255.8;
    no-cspf;
    primary to_Nagoya_ACT;
    secondary to_Nagoya_STBY;
}
path to_Nagoya_ACT {
    10.255.255.5 strict;
    10.0.0.26 loose;
}
path to_Nagoya_STBY {
    10.0.0.23 loose;
}
interface all;

secondary側にLSPが切り替わった場合、完全にIGPの最短経路で到達するようになります。

LSPを作成したら、宛先のnext-hopをLSPに向けます。

root@lab-vmx01# show | compare
[edit logical-systems Nagoya]
+   routing-options {
+       static {
+           route 10.255.255.7/32 {
+               lsp-next-hop Shinagawa;
+           }
+       }
+   }
[edit logical-systems Shinagawa]
+   routing-options {
+       static {
+           route 10.255.255.8/32 {
+               lsp-next-hop Nagoya;
+           }
+       }
+   }

RSVP LSPの確認

RSVP Neighbor

RSVPのneighborがupしていることを確認します。

root@lab-vmx01> show rsvp neighbor logical-system Nagoya
RSVP neighbor: 2 learned
Address            Idle Up/Dn LastChange HelloInt HelloTx/Rx MsgRcvd
10.0.0.22             0  1/0    10:04:09        9  3992/3992 910
10.0.0.27             5  1/0     9:05:12        9  3602/3602 728

root@lab-vmx01> show rsvp neighbor logical-system Shinagawa
RSVP neighbor: 2 learned
Address            Idle Up/Dn LastChange HelloInt HelloTx/Rx MsgRcvd
10.0.0.18             5  2/1     8:44:45        9  4469/4469 1608
10.0.0.20             0  1/0     8:48:24        9  3492/3492 30

ActivePath

ActivePathに設定したPrimary Path(to_Shinagawa_ACT & to_Nagoya_ACT)が使われていることがわかります。

root@lab-vmx01: Nagoya> show mpls lsp
Ingress LSP: 1 sessions
To              From            State Rt P     ActivePath       LSPname
10.255.255.7    10.255.255.8    Up     0 *     to_Shinagawa_ACT Shinagawa
Total 1 displayed, Up 1, Down 0

Egress LSP: 1 sessions
To              From            State   Rt Style Labelin Labelout LSPname
10.255.255.8    10.255.255.7    Up       0  1 FF       3        - Nagoya
Total 1 displayed, Up 1, Down 0

Transit LSP: 0 sessions
Total 0 displayed, Up 0, Down 0

root@lab-vmx01:Shinagawa> show mpls lsp
Ingress LSP: 1 sessions
To              From            State Rt P     ActivePath       LSPname
10.255.255.8    10.255.255.7    Up     0 *     to_Nagoya_ACT    Nagoya
Total 1 displayed, Up 1, Down 0

Egress LSP: 1 sessions
To              From            State   Rt Style Labelin Labelout LSPname
10.255.255.7    10.255.255.8    Up       0  1 FF       3        - Shinagawa
Total 1 displayed, Up 1, Down 0

Transit LSP: 0 sessions
Total 0 displayed, Up 0, Down 0

RSVP Traceroute

RSVP LSPのtracerouteでPrimary Pathを通ることが確認できます。

root@lab-vmx01:Nagoya> traceroute mpls rsvp Shinagawa
  Probe options: retries 3, exp 7

  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    1   299872  RSVP-TE     10.0.0.22        (null)           Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    2   299840  RSVP-TE     10.0.0.0         10.0.0.22        Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    3   299872  RSVP-TE     10.0.0.3         10.0.0.0         Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    4   299856  RSVP-TE     10.0.0.15        10.0.0.3         Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    5        3  RSVP-TE     10.0.0.19        10.0.0.15        Egress
  FEC-Stack-Sent: RSVP

  Path 1 via lt-0/0/0.23 destination 127.0.0.64
root@lab-vmx01:Nagoya> traceroute 10.255.255.7
traceroute to 10.255.255.7 (10.255.255.7), 30 hops max, 48 byte packets
 1  10.0.0.22 (10.0.0.22)  0.774 ms  0.493 ms  0.429 ms
     MPLS Label=299920 CoS=0 TTL=1 S=1
 2  10.0.0.0 (10.0.0.0)  0.393 ms  0.430 ms  0.412 ms
     MPLS Label=299856 CoS=0 TTL=1 S=1
 3  10.0.0.3 (10.0.0.3)  0.381 ms  0.397 ms  0.372 ms
     MPLS Label=299920 CoS=0 TTL=1 S=1
 4  10.0.0.15 (10.0.0.15)  0.379 ms  0.427 ms  0.383 ms
     MPLS Label=299888 CoS=0 TTL=1 S=1
 5  10.255.255.7 (10.255.255.7)  0.398 ms  0.386 ms  0.381 ms
root@lab-vmx01:Shinagawa> traceroute mpls rsvp Nagoya
  Probe options: retries 3, exp 7

  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    1   299872  RSVP-TE     10.0.0.18        (null)           Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    2   299840  RSVP-TE     10.0.0.8         10.0.0.18        Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    3   299792  RSVP-TE     10.0.0.25        10.0.0.8         Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    4        3  RSVP-TE     10.0.0.26        10.0.0.25        Egress
  FEC-Stack-Sent: RSVP

  Path 1 via lt-0/0/0.19 destination 127.0.0.64
root@lab-vmx01:Shinagawa> traceroute 10.255.255.8
traceroute to 10.255.255.8 (10.255.255.8), 30 hops max, 48 byte packets
 1  10.0.0.18 (10.0.0.18)  0.846 ms  0.676 ms  0.405 ms
     MPLS Label=299904 CoS=0 TTL=1 S=1
 2  10.0.0.8 (10.0.0.8)  0.368 ms  0.487 ms  0.411 ms
     MPLS Label=299856 CoS=0 TTL=1 S=1
 3  10.0.0.25 (10.0.0.25)  0.380 ms  0.385 ms  0.394 ms
     MPLS Label=299808 CoS=0 TTL=1 S=1
 4  10.255.255.8 (10.255.255.8)  0.402 ms  0.380 ms  0.375 ms

障害試験 (LSP Cutover)

上記までで正常にLSPが張れていることが確認できました。
では特定の場所やリンクで障害が起きたらどうなるでしょうか?

ここで、Ikebukuro ⇔ Shinagawa 間の回線に障害が発生 したと仮定します。 想定通りの動作であれば事前に設定したSecondary PathへLSPが高速で切り替わるはずです。

f:id:cognify:20170506105138p:plain

ここでは回線障害を模して、IkebukuroのShinagawa向けIFを明示的にshutします。

root@lab-vmx01# show | compare
[edit logical-systems Ikebukuro interfaces lt-0/0/0 unit 18]
+     disable;

これにより、ActivePathを張っていた双方向のLSPはここを通れなくなったので、どこか別の経路に迂回したはずです。
Secondary Pathには、looseモードの設定を適用したので、IGPの最短メトリックで到達すれば想定通りです。

LSPの状態確認

LSPがSecondary Path(to_Shinagawa_STBY & to_Nagoya_STBY)に切り替わっていることが確認できます。

root@lab-vmx01:Nagoya> show mpls lsp
Ingress LSP: 1 sessions
To              From            State Rt P     ActivePath       LSPname
10.255.255.7    10.255.255.8    Up     0       to_Shinagawa_STBY Shinagawa
Total 1 displayed, Up 1, Down 0

Egress LSP: 1 sessions
To              From            State   Rt Style Labelin Labelout LSPname
10.255.255.8    10.255.255.7    Up       0  1 FF       3        - Nagoya
Total 1 displayed, Up 1, Down 0

Transit LSP: 0 sessions
Total 0 displayed, Up 0, Down 0

root@lab-vmx01:Shinagawa> show mpls lsp
Ingress LSP: 1 sessions
To              From            State Rt P     ActivePath       LSPname
10.255.255.8    10.255.255.7    Up     0       to_Nagoya_STBY   Nagoya
Total 1 displayed, Up 1, Down 0

Egress LSP: 1 sessions
To              From            State   Rt Style Labelin Labelout LSPname
10.255.255.7    10.255.255.8    Up       0  1 FF       3        - Shinagawa
Total 1 displayed, Up 1, Down 0

Transit LSP: 0 sessions
Total 0 displayed, Up 0, Down 0

経路の確認

TracerouteでパスがSecondary Path になっていることが確認できます。
Nagoya → Dojima → Shibuya → Toyosu → Shinagawaの経路になっています。これはOSPFの最小メトリック経路とも一致します。

root@lab-vmx01:Nagoya> traceroute mpls rsvp Shinagawa
  Probe options: retries 3, exp 7

  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    1   299888  RSVP-TE     10.0.0.22        (null)           Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    2   299888  RSVP-TE     10.0.0.11        10.0.0.22        Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    3   299808  RSVP-TE     10.0.0.17        10.0.0.11        Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    4        3  RSVP-TE     10.0.0.21        10.0.0.17        Egress
  FEC-Stack-Sent: RSVP

  Path 1 via lt-0/0/0.23 destination 127.0.0.64

f:id:cognify:20170506105308p:plain

戻りの経路も同様にIGPの最短経路で上記の逆方向になっています。

root@lab-vmx01:Shinagawa> traceroute mpls rsvp Nagoya
  Probe options: retries 3, exp 7

  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    1   299824  RSVP-TE     10.0.0.20        (null)           Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    2   299904  RSVP-TE     10.0.0.16        10.0.0.20        Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    3   299904  RSVP-TE     10.0.0.10        10.0.0.16        Success
  FEC-Stack-Sent: RSVP
  ttl    Label  Protocol    Address          Previous Hop     Probe Status
    4        3  RSVP-TE     10.0.0.23        10.0.0.10        Egress
  FEC-Stack-Sent: RSVP

  Path 1 via lt-0/0/0.21 destination 127.0.0.64

f:id:cognify:20170506105328p:plain

Ikebukuro ⇔ Shinagawa間のLSPステータスがDeadとなっています。IFを解放して障害が復旧すれば、再度status upに戻ります。
一度DownしたLSPが再度安定した状態とみなされるまでには、retry-timerの2倍の時間がかかります。

root@lab-vmx01:Shinagawa> show rsvp neighbor detail
RSVP neighbor: 2 learned
Address: 10.0.0.18 via: lt-0/0/0.19 status: Dead
  Last changed time: 3:33, Idle: 3:40 sec, Up cnt: 2, Down cnt: 2
  Message received: 1624
  Hello: sent 4511, received: 4511, interval: 9 sec
  Remote instance: 0x0, Local instance: 0x18d0c77e
  Refresh reduction:  not operational

Transit LSRの状態も確認すると、PrimaryがDownしてSecondaryがUpしているのが確認できます。

root@lab-vmx01: Shibuya> show mpls lsp logical-system
Ingress LSP: 0 sessions
Total 0 displayed, Up 0, Down 0

Egress LSP: 0 sessions
Total 0 displayed, Up 0, Down 0

Transit LSP: 3 sessions
To              From            State   Rt Style Labelin Labelout LSPname
10.255.255.7    10.255.255.8    Dn       0  0  -       -        - Shinagawa
10.255.255.7    10.255.255.8    Up       0  1 FF  299888   299808 Shinagawa
10.255.255.8    10.255.255.7    Up       0  1 FF  299904   299904 Nagoya
Total 3 displayed, Up 2, Down 1

ここまででLSPの切り替えを確認できました。
この機能を使うとユーザトラフィックの中断を最小限に抑えた遅延の少ないLSP移行が簡単にできます。

まとめ

今回はRSVPでのLSPのシグナリングを行いました。
あまり良い例ではありませんでしたが、RSVPシグナリングとHot Standby LSPのRepairが確認できました。
前回と合わせてMPLSネットワークの基本であるLSP制御についてはある程度触れたので、次回から本格的なノード障害時のプロテクション動作や、高速なReRoute動作について確認していきたいと思います。

Junosで始めるMPLS入門 その1 Static LSP編

これから何回かに分けてJunosのMPLSで遊んでみようと思います。
特に面白いネタがあるわけでもありませんが、最近MPLSをベースにした技術ネタについて話す機会が多くなったので、基礎から一通りまとめてみます。
最終的には、MPLS-EVPNやSegment Routing(動けば)なども扱う予定です。

MPLS とは

RFC読んでください。
ラベル情報を元にパケットを転送する技術です。
昔はIPベースのルーティングより高速と言われていましたが、ルータの性能も飛躍的に向上したので、パトリシアツリーの検索を行うIPルーティングと比較しても速度的には大差はありません。
現在のMPLSは、ラベルをスタックすることで実現可能なIP-VPNサービスや、FRR、トラフィックエンジニアリングなどの運用面での利用が主流です。

ラベル構造

”SHIM Header” でググってください。
32bitの固定長の空間に20bitのlabel valueとlabel stackのための情報などが入っています。

MPLSの基本動作

MPLSのラベルオペレーションには基本的に以下の3つの操作しかありません。

  • Push
    • ラベルをパケットの先頭に追加する操作
    • ラベルは複数追加することが可能です(ラベルスタック)
  • Pop
    • パケットの先頭からラベルを削除する操作
    • 複数ラベルがスタックされている場合、下のラベルは削除されません
  • Swap
    • 先頭のラベルを新しいラベルで置き換える操作
    • パケットを中継するルータで必要な動作です

付ける、剥がす、置き換えるです。
SwapとPushを同時に行うこともあります。
この3つの動作を組み合わせて、IP-VPNや高度なトラフィックエンジニアリングを実現しています。

MPLSは上記のラベルの操作と転送は実施しますが、ラベル情報そのものの交換や割り当ては行わないので、動的にラベル情報を通知・要求するプロトコルや、手動設定でラベル情報を交換する必要があります。

ラベルとIPアドレスの決定的な違い

ルーティングに使用するIPアドレスと、MPLSで使用するラベルの役割の大きな違いは以下です。

  • MPLS ラベル
    • そのルータとリンクでのみユニークであれば良い
  • IPアドレス
    • そのネットワーク全体(ドメイン)でユニークである必要がある

MPLSがかつて高速な処理といわれていたのにも上記の違いが大きく影響しています。

ラボ環境

実際に小規模なラボを作って動作を見ていきます。

  • Server
  • Router
    • Juniper vMX 17.1 KVM
      • logical-systemで論理ルータを切り出し、logical-tunnnelで接続します
      • 入手・設定方法はブログ等で散々書かれていますのでググってください

構成図

日本国内の拠点を以下のように接続したトポロジを考えます。
※実在する組織や拠点とは一切関係ありません 。
f:id:cognify:20170504232338j:plain
ほかの検証で利用した構成を流用したので、あまりイケてないですが今回はこれでやります。

事前準備

logical-system の設定

各拠点分のルータをlogical-systemで作成します。
ls間はlogical tunnel(lt)で接続します。

余談ですが、logical-systemでは以下のコマンドで各論理ルータにログインすることができます。
コマンドを打つ度にlogical-systemの指定をしなくてよくなります。

root@lab-vmx01> set cli logical-system Fukuoka
Logical system: Fukuoka
root@lab-vmx01:Fukuoka> 
root@lab-vmx01:Fukuoka> clear cli logical-system
Cleared default logical system
root@lab-vmx01>

IGPの設定

宛先Prefixをラベル情報にマッピングする場合、予め経路情報をIGPで収束しておく必要があるため、各ルータでOSPFを有効にします。

root@lab-vmx01:Fukuoka> show configuration protocols ospf
area 0.0.0.0 {
    interface all;
}

Static LSPによる制御

先ずはLDPなどを使わずに、ラベルを手動で割り当てて制御してみます。
これは 非常に面倒でミスをしやすい やり方なので通常運用ではあまり行いません。
LSPは一方向のパスなので、行きと戻りで2本作ります。

ここではFukuokaからToyosuへのパスを考えます。
双方向のパスが違う経路を通るようにします。

Fukuoka→Toyosu 方向

Fukuokaのloopback 10.255.255.9からToyosuのloopback 10.255.255.6への経路をstatic LSPで設定します。
Fukuoka→Nagoya→Dojima→Otemachi→Shibuya→Toyosu の順に通します。

行きのパス

f:id:cognify:20170504232411j:plain

Fukuoka→Toyosu 方向のラベル操作は以下の順で実施します。
1. Fukuokaでラベル1000001をpush,Nagoyaへ転送
2. Nagoyaでラベル1000001を1000002にswap,Dojimaへ転送
3. Dojimaでラベル1000002を1000003にswap,Otemachiへ転送
4. Otemachiでラベル1000003を1000004にswap,Shibuyaへ転送
5. Shibuyaでラベル1000004を0にswap=pop(PHP),Toyosuへ転送
6. ラベルが剝がされたパケットがToyosuに到達

ingress LSRとなるFukuokaで、ラベル1000001をパケットにpushします。
Toyosu向けのstatic lspを定義し、ネクストホップをNagoyaに向けます。
また、宛先となるToyosuのloopbackをMPLSのルーティングテーブルであるinet.3にインストールします。

root@lab-vmx01:Fukuoka> show configuration protocols mpls
static-label-switched-path to_Toyosu {
    ingress {
        install 10.255.255.6/32;
        next-hop 10.0.0.26;
        to 10.0.0.17;
        push 1000001;
    }
}
interface all;

宛先のstatic routeをlspに向けます。

root@lab-vmx01:Fukuoka> show configuration routing-options
static {
    route 10.255.255.6/32 {
        static-lsp-next-hop to_Toyosu;
    }
}

設定どおり1000001をpushする動作になっていることがわかります。

root@lab-vmx01:Fukuoka> show route table inet.0 protocol static

inet.0: 26 destinations, 27 routes (26 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.255.255.6/32    *[Static/5] 04:54:46
                    > to 10.0.0.26 via lt-0/0/0.27, Push 1000001

root@lab-vmx01:Fukuoka> show route table inet.3

inet.3: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

10.0.0.17/32       *[MPLS/6/1] 02:01:11, metric 0
                    > to 10.0.0.26 via lt-0/0/0.27, Push 1000001
10.255.255.6/32    *[MPLS/6/1] 02:01:11, metric 0
                    > to 10.0.0.26 via lt-0/0/0.27, Push 1000001

Nagoya,Dojima,OtemachiはTransit LSRとなります。
つまり中継ルータです。swapを行い、PushやPopは行いません。
ここでは一つ前のLSRがswap(push)してきたラベルを判別し、新しいラベルにswapしています。
例えば、DojimaではNagoyaがswapした1000002というラベルを受け取ったら新しく1000003というラベルにswapするという設定をしています。

root@lab-vmx01:Nagoya> show configuration protocols mpls
static-label-switched-path to_Toyosu {
    transit 1000001 {
        next-hop 10.0.0.22;
        swap 1000002;
    }
}
interface all;

root@lab-vmx01:Dojima> show configuration protocols mpls
static-label-switched-path to_Toyosu {
    transit 1000002 {
        next-hop 10.0.0.0;
        swap 1000003;
    }
}
interface all;

root@lab-vmx01:Otemachi> show configuration protocols mpls
static-label-switched-path to_Toyosu {
    transit 1000003 {
        next-hop 10.0.0.3;
        swap 1000004;
    }
}
interface all;
root@lab-vmx01:Dojima> show route table mpls.0

mpls.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0                  *[MPLS/0] 07:05:17, metric 1
                      Receive
1                  *[MPLS/0] 07:05:17, metric 1
                      Receive
2                  *[MPLS/0] 07:05:17, metric 1
                      Receive
13                 *[MPLS/0] 07:05:17, metric 1
                      Receive
1000002            *[MPLS/6] 02:34:18, metric 1
                    > to 10.0.0.0 via lt-0/0/0.1, Swap 1000003

以上が、transit LSRの設定になります。

Shibuyaは少し特殊な設定をします。
ShibuyaもToyosu向けの中継ルータであることには変わりありませんが、Toyosuの一つ前、つまり最後から二番目(Penultimate)のホップに位置するルータですので、ここでラベルをswapする意味がありません。
ラベルをここでpopしてネクストホップへ転送しても、次は宛先のToyosuなので問題ないはずです。
なのでここではラベルをpopする設定を入れます。
これが Penultimate Hop Popping(PHP) という動作です。
LDPなどを有効にしている場合、JunosはこのPHPをデフォルトで実行します。

root@lab-vmx01:Shibuya> show configuration protocols mpls
static-label-switched-path to_Toyosu {
    transit 1000004 {
        next-hop 10.0.0.17;
        swap 0;
    }
}

popという明示的な設定もありますが、ここではラベル0にswapしています。
このラベル0は特殊なラベルで受信時にラベルをpopしIPパケットとして転送することを意味します。
1000004を受信したときの動作がS=0 Popとなっていることがわかります。

root@lab-vmx01:Shibuya:> show route table mpls.0

mpls.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

0                  *[MPLS/0] 07:07:32, metric 1
                      Receive
1                  *[MPLS/0] 07:07:32, metric 1
                      Receive
2                  *[MPLS/0] 07:07:32, metric 1
                      Receive
13                 *[MPLS/0] 07:07:32, metric 1
                      Receive
1000004            *[MPLS/6] 02:31:45, metric 1
                    > to 10.0.0.17 via lt-0/0/0.16, Swap 0
1000004(S=0)       *[MPLS/6] 02:31:45, metric 1
                    > to 10.0.0.17 via lt-0/0/0.16, Pop

Toyosu→Fukuoka 方向

Toyosu→Shinagawa→Ikebukuro→Shinsaibasi→Fukuoka の順に通します。

戻りのパス

f:id:cognify:20170504232604j:plain 上記と同様の設定を戻りの経路にするだけです。

Toyosu→Fukuoka 方向のラベル操作は以下の順で実施します。
1. Toyosuでラベル1000101をpush,Shinagawaへ転送
2. Shinagawaでラベル1000101を1000102にswap,Ikebukuroへ転送
3. Ikebukuroでラベル1000102を1000103にswap,Shinsaibashiへ転送
4. Shinsaibashiでラベル1000103を0にswap=pop(PHP),Fukuokaへ転送
5. ラベルが剝がされたパケットがFukuokaに到達

確認

双方向で明示的に指定したパスで到達していることが確認できます。

traceroute: Fukuoka → Toyosu

f:id:cognify:20170505062703j:plain

root@lab-vmx01:Fukuoka> traceroute 10.255.255.6 source 10.255.255.9
traceroute to 10.255.255.6 (10.255.255.6) from 10.255.255.9, 30 hops max, 48 byte packets
 1  10.0.0.26 (10.0.0.26)  0.793 ms  0.523 ms  0.420 ms
     MPLS Label=1000001 CoS=0 TTL=1 S=1
 2  10.0.0.22 (10.0.0.22)  0.406 ms  0.357 ms  0.373 ms
     MPLS Label=1000002 CoS=0 TTL=1 S=1
 3  10.0.0.0 (10.0.0.0)  0.373 ms  0.388 ms  0.395 ms
     MPLS Label=1000003 CoS=0 TTL=1 S=1
 4  10.0.0.3 (10.0.0.3)  0.416 ms  0.396 ms  0.432 ms
     MPLS Label=1000004 CoS=0 TTL=1 S=1
 5  10.255.255.6 (10.255.255.6)  0.465 ms  0.393 ms  0.383 ms
traceroute: Toyosu → Fukuoka

f:id:cognify:20170505062722j:plain

root@lab-vmx01:Toyosu> traceroute 10.255.255.9 source 10.255.255.6
traceroute to 10.255.255.9 (10.255.255.9) from 10.255.255.6, 30 hops max, 48 byte packets
 1  10.0.0.21 (10.0.0.21)  0.915 ms  0.605 ms  0.365 ms
     MPLS Label=1000101 CoS=0 TTL=1 S=1
 2  10.0.0.18 (10.0.0.18)  0.381 ms  0.384 ms  0.401 ms
     MPLS Label=1000102 CoS=0 TTL=1 S=1
 3  10.0.0.8 (10.0.0.8)  0.424 ms  0.368 ms  0.368 ms
     MPLS Label=1000103 CoS=0 TTL=1 S=1
 4  10.255.255.9 (10.255.255.9)  0.359 ms  0.353 ms  0.372 ms

LSPを用いない場合、単純にIGPであるOSPFの最小メトリックがベストパスになります。

特殊なラベル

一部のラベル(0-15)は予約ラベルといって用途が決まっています。
よく使うのは以下の4つなので覚えておくと便利です。

  • 0: IPv4 Explicit Null label
  • 1: Router Alert label
  • 2: IPv6 Explicit Null label
  • 3: Implicit Null label

まとめ

今回はMPLSの基本動作をみるために手動でラベル設定を行いました。
上記のように手動でラベル操作を設定することも可能ですが、あまりにも手間がかかるので通常はLDPやRSVPを用いてシグナリングすることが多いです。
運用上どうしても手動でパスを設定する必要がある場合以外は動的な設定を推奨します。

次回からLDP/RSVPを用いた動的な設定や、トラフィックエンジニアリングについて書いていきたいと思います。