IGP を v6 only にした話 — OSPF から IS-IS unnumbered へ

underlay を OSPF から IS-IS に移行しました。ルータ間のリンクにアドレスを振らない unnumbered にするのが目的で、結果として IGP が v6 しか運ばない構成になりました。

やりたかったこと

出発点は unnumbered にしたかった ことです。ルータ間の p2p リンクにアドレスを振らずに隣接が張れるのは単純に格好いいと思っていて、ずっとやってみたかった構成でした。

どれで unnumbered をやるか

やり方は大きく二つあります。BGP unnumbered で underlay ごと BGP に寄せるか、IGP を IS-IS に載せ替えるかです。

IS-IS を選びました。理由は、いずれ Segment Routing をやりたいからです。SR は IGP の拡張として入るので、IGP を捨てる方向には行きたくない。それなら IS-IS だろう、という感じでした。IS-IS は隣接そのものが L2 (CLNS) ネイティブなので、IP アドレスが無いのが例外ではなく素の状態なのも噛み合っています。

決め手はそのくらいで、OSPF との細かい比較はあまりしていません。

当初の想定

やるのは リンクの unnumbered 化だけのつもりでした。リンクからアドレスが無くなるので、隣接は v6 リンクローカルで張ります。

loopback の v4 は、そのまま IS-IS で配るつもりでいました。 router-id など識別子として使うので loopback には v4 が残りますし、IS-IS は元々 multi-protocol なので v4 と v6 の prefix を同じ LSP に載せられます。next-hop が v6 リンクローカルしか無くても解決してくれるだろう、BGP でいう RFC 8950 (extended next-hop) のような挙動になるはずだ、と思っていました。

ここが崩れます。

本番の1リンクで試してみる

いきなり全台やるのは怖いので、コアとボーダの間の1リンクだけで試すことにしました。IS-IS の隣接は L2 なので OSPF と干渉しません。並走させて (ships-in-the-night) 様子を見ながら進める作戦です。

まず numbered のまま IS-IS を入れてみます。隣接はあっさり上がりました。v4 も v6 も普通に載ります。ここまでは想定通りでした。

次が本題です。リンクからアドレスを消したらどうなるのか。 v4 と v6 の GUA を両方消して、リンクローカルだけにしてみました。

IS-IS の隣接は維持されます。v6 の loopback も fe80 の next-hop でちゃんと入ってきます。目的だった unnumbered は、この時点で成立していました。

期待していたのは、ここで v4 の loopback も一緒に入ってくることでした。

show route 202.222.160.2
→ 経路自体は出てくるが hidden

入りませんでした。

LSP には v4 の prefix が載っています。SPF も回っています。それでも RIB に install されない。next-hop として使えるのが v6 のリンクローカルしか無いので、そこで止まっているようでした。

面白いのは、同じ条件で FRR 側 (VyOS) だと install される ことです。JunOS だけが入れてくれない。実装の違いなのか、それとも何か設定で有効にできるのか、そこまでは追い切れていません。少なくとも 23.4 系ではこうなりました。

loopback を借用する unnumbered-address lo0.0 も試しました。こちらは経路自体は出るものの、Ethernet だと ARP が解決できずに hold のまま止まります。対向側のアドレスを教える方法が見つかりませんでした。

v4 loopback は BGP に任せる

というわけで「v4 loopback も IS-IS で」は諦めました。unnumbered という本来の目的はもう達成しているので、残るのは v4 をどこで運ぶかだけです。

これは BGP に載せることにしました。iBGP を v6 の loopback 間で1セッション張り、RFC 8950 (extended next-hop) で v4 と v6 の両方を運びます。IS-IS でやりたかった「v4 の prefix を v6 の next-hop で」を、BGP なら素直にやってくれます。

結果的に underlay は IS-IS、service は BGP という層の分離になって、これはこれで見通しが良くなりました。IGP が service 経路を持たないので、依存の向きが一方通行になります。

RFC 8950 が手元の MX240 (Trio) で本当に動くのかは確認しておきたかったので、これも先に実験しました。既存の v6 iBGP に v4 の address-family と extended-nexthop を足して、v4 の /32 を交換させます。

RIB にも FIB にも v6 リンクローカルを next-hop として入りました。ping も通ります。BGP では普通に動きます。

同じ「v4 を v6 の next-hop で」でも、BGP ではできて IS-IS ではできない。この差は少し不思議でした。

空の family inet が要る

この実験中に一つ引っかかったことがあります。

経路表は完全に正常なのに ping が通らない、という状態にハマりました。しばらく経路を疑って時間を溶かしたのですが、原因は JunOS が v4 をトランジットするリンクに空の family inet を要求する ことでした。

set interfaces xe-0/0/0 unit 0 family inet     ← アドレスは無いが必要
set interfaces xe-0/0/0 unit 0 family inet6    ← リンクローカルのみ
set interfaces xe-0/0/0 unit 0 family iso      ← IS-IS 用

family inet を丸ごと消すと、着信した v4 パケットがインターフェースの時点で捨てられます。RIB も FIB も緑のままなので、経路を見ている限り絶対に気づけません。unnumbered 化のときは「アドレスだけ消して family は残す」を徹底する必要があります。

全台に展開する

方針が固まったので、残りのノードにも広げていきます。手順は三段階にしました。

1. IS-IS を全ノードに投入して、隣接を全部 Up にする

OSPF はそのまま動かしたまま並走させます。IS-IS が増えるだけなので無停止です。

2. 全ノードで全 loopback が IS-IS 経由でも見えることを確認してから、OSPFv3 を撤去

ここにゲートを置くのが重要でした。JunOS の経路優先度は OSPF3 が 10、IS-IS L2 が 18 なので、並走中は OSPFv3 が選ばれます。つまり IS-IS 側が正しく計算できているかどうかは、OSPFv3 を抜くまで表に出ません。抜いてから「実は入っていなかった」では遅いので、show route protocol isis で1台ずつ全部の loopback が見えることを確認してから撤去しました。

3. リンクから v4 アドレスと v6 GUA を削除して unnumbered 化

ここで前述の「空の family inet は残す」が効いてきます。

各段階のあと、iBGP が全部 Established のままか、実際のサービスが通るか、を毎回確認してから次へ進みました。

機材

機材 台数 役割
Juniper MX240 (Junos 23.4R1-S1.5) 2 コアルータ
VyOS (FRR 10.x) 2 ボーダルータ、transit 収容
Cisco Catalyst 4948E (IOS 15.2(4)E10) 1 エッジスイッチ

できあがったもの

  • IGP は IS-IS の v6 only。 ルータ間のリンクは v6 リンクローカルと family iso、それに空の family inet だけ
  • v4 は BGP (RFC 8950) で運搬。 iBGP は v6 の loopback 間で1セッション
  • OSPF (v2/v3) は AS から消滅
  • エッジ向けの1ペアを除いて、リンクは全部 unnumbered

設定量は目に見えて減りました。リンクを1本足すときに書くのは family inet (空) / family inet6 / family iso / IS-IS の point-to-point の4行だけです。アドレスの採番が要らないので IPAM を開く回数が減りました。地味ですが、これが一番うれしい変化かもしれません。

v4 の loopback まで IS-IS に載せる、という当初の想定は外れましたが、unnumbered という本来の目的は達成できました。そして外れた結果として、IGP が v6 しか運ばない構成になりました。underlay から v4 が消えると、どの経路がどのレイヤの仕事なのかが自然と整理されます。unnumbered も含めて、やってみると気持ちのいい構成でした。

この記事の著者

ゆっぷりん