[要約] RFC 7811は、IP/LDP Fast Rerouteを計算するためのMRT-FRRアルゴリズムについての要約です。目的は、ネットワークの冗長性を最大化し、高速な経路の切り替えを実現することです。

Internet Engineering Task Force (IETF)                         G. Enyedi
Request for Comments: 7811                                    A. Csaszar
Category: Standards Track                                       Ericsson
ISSN: 2070-1721                                                 A. Atlas
                                                               C. Bowers
                                                        Juniper Networks
                                                              A. Gopalan
                                                   University of Arizona
                                                               June 2016
        

An Algorithm for Computing IP/LDP Fast Reroute Using Maximally Redundant Trees (MRT-FRR)

最大冗長ツリー(MRT-FRR)を使用してIP / LDP高速リルートを計算するアルゴリズム

Abstract

概要

This document supports the solution put forth in "An Architecture for IP/LDP Fast Reroute Using Maximally Redundant Trees (MRT-FRR)" (RFC 7812) by defining the associated MRT Lowpoint algorithm that is used in the Default MRT Profile to compute both the necessary Maximally Redundant Trees with their associated next hops and the alternates to select for MRT-FRR.

このドキュメントは、デフォルトのMRTプロファイルで両方を計算するために使用される関連するMRTローポイントアルゴリズムを定義することにより、「最大冗長ツリーを使用したIP / LDP高速リルート(MRT-FRR)のアーキテクチャ」(RFC 7812)で提案されたソリューションをサポートします。必要な最大冗長ツリーとそれに関連するネクストホップ、およびMRT-FRRに選択する代替。

Status of This Memo

本文書の状態

This is an Internet Standards Track document.

これはInternet Standards Trackドキュメントです。

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841.

このドキュメントは、IETF(Internet Engineering Task Force)の製品です。これは、IETFコミュニティのコンセンサスを表しています。公開レビューを受け、インターネットエンジニアリングステアリンググループ(IESG)による公開が承認されました。インターネット標準の詳細については、RFC 7841のセクション2をご覧ください。

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc7811.

このドキュメントの現在のステータス、エラータ、およびフィードバックの提供方法に関する情報は、http://www.rfc-editor.org/info/rfc7811で入手できます。

Copyright Notice

著作権表示

Copyright (c) 2016 IETF Trust and the persons identified as the document authors. All rights reserved.

Copyright(c)2016 IETF Trustおよびドキュメントの作成者として識別された人物。全著作権所有。

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

この文書は、BCP 78およびIETF文書に関するIETFトラストの法的規定(http://trustee.ietf.org/license-info)の対象であり、この文書の発行日に有効です。これらのドキュメントは、このドキュメントに関するあなたの権利と制限を説明しているため、注意深く確認してください。このドキュメントから抽出されたコードコンポーネントには、Trust Legal Provisionsのセクション4.eに記載されているSimplified BSD Licenseのテキストが含まれている必要があり、Simplified BSD Licenseに記載されているように保証なしで提供されます。

Table of Contents

目次

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
   2.  Requirements Language . . . . . . . . . . . . . . . . . . . .   5
   3.  Terminology and Definitions . . . . . . . . . . . . . . . . .   5
   4.  Algorithm Key Concepts  . . . . . . . . . . . . . . . . . . .   6
     4.1.  Partial Ordering for Disjoint Paths . . . . . . . . . . .   7
     4.2.  Finding an Ear and the Correct Direction  . . . . . . . .   8
     4.3.  Lowpoint Values and Their Uses  . . . . . . . . . . . . .  11
     4.4.  Blocks in a Graph . . . . . . . . . . . . . . . . . . . .  14
     4.5.  Determining Localroot and Assigning Block-ID  . . . . . .  16
   5.  MRT Lowpoint Algorithm Specification  . . . . . . . . . . . .  18
     5.1.  Interface Ordering  . . . . . . . . . . . . . . . . . . .  18
     5.2.  MRT Island Identification . . . . . . . . . . . . . . . .  21
     5.3.  GADAG Root Selection  . . . . . . . . . . . . . . . . . .  21
     5.4.  Initialization  . . . . . . . . . . . . . . . . . . . . .  22
     5.5.  Constructing the GADAG Using Lowpoint Inheritance . . . .  23
     5.6.  Augmenting the GADAG by Directing All Links . . . . . . .  25
     5.7.  Compute MRT Next Hops . . . . . . . . . . . . . . . . . .  29
       5.7.1.  MRT Next Hops to All Nodes Ordered with Respect to
               the Computing Node  . . . . . . . . . . . . . . . . .  29
       5.7.2.  MRT Next Hops to All Nodes Not Ordered with Respect
               to the Computing Node . . . . . . . . . . . . . . . .  30
       5.7.3.  Computing Redundant Tree Next Hops in a 2-Connected
               Graph . . . . . . . . . . . . . . . . . . . . . . . .  31
       5.7.4.  Generalizing for a Graph That Isn't 2-Connected . . .  33
       5.7.5.  Complete Algorithm to Compute MRT Next Hops . . . . .  34
     5.8.  Identify MRT Alternates . . . . . . . . . . . . . . . . .  36
     5.9.  Named Proxy-Nodes . . . . . . . . . . . . . . . . . . . .  44
       5.9.1.  Determining Proxy-Node Attachment Routers . . . . . .  45
       5.9.2.  Computing If an Island Neighbor (IN) Is Loop-Free . .  45
       5.9.3.  Computing MRT Next Hops for Proxy-Nodes . . . . . . .  47
       5.9.4.  Computing MRT Alternates for Proxy-Nodes  . . . . . .  53
        
   6.  MRT Lowpoint Algorithm: Next-Hop Conformance  . . . . . . . .  61
   7.  Broadcast Interfaces  . . . . . . . . . . . . . . . . . . . .  61
     7.1.  Computing MRT Next Hops on Broadcast Networks . . . . . .  62
     7.2.  Using MRT Next Hops as Alternates in the Event of
           Failures on Broadcast Networks  . . . . . . . . . . . . .  63
   8.  Evaluation of Alternative Methods for Constructing GADAGs . .  64
   9.  Operational Considerations  . . . . . . . . . . . . . . . . .  66
     9.1.  GADAG Root Selection  . . . . . . . . . . . . . . . . . .  67
     9.2.  Destination-Rooted GADAGs . . . . . . . . . . . . . . . .  67
   10. Security Considerations . . . . . . . . . . . . . . . . . . .  67
   11. References  . . . . . . . . . . . . . . . . . . . . . . . . .  68
     11.1.  Normative References . . . . . . . . . . . . . . . . . .  68
     11.2.  Informative References . . . . . . . . . . . . . . . . .  68
   Appendix A.  Python Implementation of MRT Lowpoint Algorithm  . .  70
   Appendix B.  Constructing a GADAG Using SPFs  . . . . . . . . . . 110
   Appendix C.  Constructing a GADAG Using a Hybrid Method . . . . . 115
   Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . . 117
   Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . . 118
        
1. Introduction
1. はじめに

MRT Fast Reroute requires that packets can be forwarded not only on the shortest-path tree, but also on two Maximally Redundant Trees (MRTs), referred to as the MRT-Blue and the MRT-Red. A router that experiences a local failure must also have predetermined which alternate to use. This document defines how to compute these three things for use in MRT-FRR and describes the algorithm design decisions and rationale. The algorithm is based on those presented in [MRTLinear] and expanded in [EnyediThesis]. The MRT Lowpoint algorithm is required for implementation when the Default MRT Profile is implemented.

MRT高速リルートでは、最短パスツリーだけでなく、MRT-BlueおよびMRT-Redと呼ばれる2つの最大冗長ツリー(MRT)でもパケットを転送できる必要があります。ローカルの障害が発生したルーターも、使用する代替を事前に決定しておく必要があります。このドキュメントでは、MRT-FRRで使用するためにこれら3つの事柄を計算する方法を定義し、アルゴリズム設計の決定と理論的根拠について説明します。アルゴリズムは、[MRTLinear]で提示され、[EnyediThesis]で拡張されたものに基づいています。デフォルトのMRTプロファイルが実装されている場合、実装にはMRTローポイントアルゴリズムが必要です。

The MRT Lowpoint Algorithm defined in this document, when used for MRT Fast-Reroute as described in [RFC7812], guarantees 100% recovery for single failures when the network is 2-connected. This guaranteed coverage does not depend on the link metrics, which an operator may be using to traffic-engineer the IP network. Thus, the link metrics and general network topology are largely decoupled from the guaranteed coverage.

このドキュメントで定義されているMRTローポイントアルゴリズムは、[RFC7812]で説明されているようにMRT高速リルートに使用されると、ネットワークが2つ接続されている場合に単一の障害に対して100%の回復を保証します。この保証されたカバレッジは、オペレーターがIPネットワークのトラフィックエンジニアリングに使用している可能性があるリンクメトリックに依存しません。したがって、リンクメトリックと一般的なネットワークトポロジは、保証されるカバレッジから大きく切り離されます。

Just as packets routed on a hop-by-hop basis require that each router compute a shortest-path tree that is consistent, it is necessary for each router to compute the MRT-Blue next hops and MRT-Red next hops in a consistent fashion. This document defines the MRT Lowpoint algorithm to be used as a standard in the Default MRT Profile for MRT-FRR.

ホップバイホップでルーティングされるパケットでは、各ルーターが一貫した最短パスツリーを計算する必要があるのと同様に、各ルーターはMRT-BlueネクストホップとMRT-Redネクストホップを一貫した方法で計算する必要があります。 。このドキュメントでは、MRT-FRRのデフォルトMRTプロファイルで標準として使用されるMRTローポイントアルゴリズムを定義します。

A router's Forwarding Information Base (FIB) will continue to contain primary next hops for the current shortest-path tree for forwarding traffic. In addition, a router's FIB will contain primary next hops for the MRT-Blue for forwarding received traffic on the MRT-Blue and primary next hops for the MRT-Red for forwarding received traffic on the MRT-Red.

ルーターの転送情報ベース(FIB)には、トラフィックを転送するための現在の最短パスツリーのプライマリネクストホップが引き続き含まれます。さらに、ルータのFIBには、MRT-Blueで受信したトラフィックを転送するためのMRT-Blueのプライマリネクストホップと、MRT-Redで受信したトラフィックを転送するMRT-Redのプライマリネクストホップが含まれます。

What alternate next hops a Point of Local Repair (PLR) selects need not be consistent -- but loops must be prevented. To reduce congestion, it is possible for multiple alternate next hops to be selected; in the context of MRT alternates, each of those alternate next hops would be equal-cost paths.

Point of Local Repair(PLR)が選択する代替ネクストホップは一貫している必要はありませんが、ループは防止する必要があります。輻輳を減らすために、複数の代替ネクストホップを選択することが可能です。 MRT代替のコンテキストでは、これらの代替ネクストホップのそれぞれが等コストパスになります。

This document defines an algorithm for selecting an appropriate MRT alternate for consideration. Other alternates, e.g., Loop-Free Alternates (LFAs) that are downstream paths, may be preferred when available. See the "Operational Considerations" section of [RFC7812] for a more detailed discussion of combining MRT alternates with those produced by other FRR technologies.

このドキュメントでは、検討のために適切なMRT代替を選択するためのアルゴリズムを定義します。ダウンストリームパスであるループフリーオルタネート(LFA)などの他の代替手段が利用可能な場合は、それが優先される場合があります。 MRT代替と他のFRRテクノロジーによって生成される代替の組み合わせの詳細については、[RFC7812]の「運用上の考慮事項」セクションを参照してください。

   [E]---[D]---|           [E]<--[D]<--|                [E]-->[D]---|
    |     |    |            |     ^    |                       |    |
    |     |    |            V     |    |                       V    V
   [R]   [F]  [C]          [R]   [F]  [C]               [R]   [F]  [C]
    |     |    |                  ^    ^                 ^     |    |
    |     |    |                  |    |                 |     V    |
   [A]---[B]---|           [A]-->[B]---|                [A]<--[B]<--|
        

(a) (b) (c) A 2-connected graph MRT-Blue towards R MRT-Red towards R

(a)(b)(c)2連結グラフMRT-青からRへMRT-赤からRへ

Figure 1

図1

The MRT Lowpoint algorithm can handle arbitrary network topologies where the whole network graph is not 2-connected, as in Figure 2, as well as the easier case where the network graph is 2-connected (Figure 1). Each MRT is a spanning tree. The pair of MRTs provide two paths from every node X to the root of the MRTs. Those paths share the minimum number of nodes and the minimum number of links. Each such shared node is a cut-vertex. Any shared links are cut-links.

MRTローポイントアルゴリズムは、図2のようにネットワークグラフ全体が2接続されていない任意のネットワークトポロジーや、ネットワークグラフが2接続されている簡単なケース(図1)を処理できます。各MRTはスパニングツリーです。 MRTのペアは、すべてのノードXからMRTのルートへの2つのパスを提供します。これらのパスは、最小数のノードと最小数のリンクを共有します。このような各共有ノードはカット頂点です。共有リンクはすべてカットリンクです。

                        [E]---[D]---|     |---[J]
                         |     |    |     |    |
                         |     |    |     |    |
                        [R]   [F]  [C]---[G]   |
                         |     |    |     |    |
                         |     |    |     |    |
                        [A]---[B]---|     |---[H]
        

(a) a graph that is not 2-connected

(a)2連結でないグラフ

         [E]<--[D]<--|         [J]        [E]-->[D]---|     |---[J]
          |     ^    |          |                |    |     |    ^
          V     |    |          |                V    V     V    |
         [R]   [F]  [C]<--[G]   |         [R]   [F]  [C]<--[G]   |
                ^    ^     ^    |          ^     |    |          |
                |    |     |    V          |     V    |          |
         [A]-->[B]---|     |---[H]        [A]<--[B]<--|         [H]
        

(b) MRT-Blue towards R (c) MRT-Red towards R

(b)Rに向かうMRT-Blue(c)Rに向かうMRT-Red

Figure 2: A Network That Is Not 2-Connected

図2:2接続されていないネットワーク

2. Requirements Language
2. 要件言語

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

このドキュメントのキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「MAY」、および「OPTIONAL」は、 [RFC2119]で説明されているように解釈されます。

3. Terminology and Definitions
3. 用語と定義

Please see the Terminology section of [RFC7812] for a complete list of terminology relevant to this document. The list below does not repeat terminology introduced in that RFC.

このドキュメントに関連する用語の完全なリストについては、[RFC7812]の用語セクションを参照してください。以下のリストは、そのRFCで導入された用語を繰り返さない。

spanning tree: A tree that contains links and that connects all nodes in the network graph.

スパニングツリー:リンクを含み、ネットワークグラフ内のすべてのノードを接続するツリー。

back-edge: In the context of a spanning tree computed via a depth-first search, a back-edge is a link that connects a descendant of a node x with an ancestor of x.

バックエッジ:深さ優先検索で計算されたスパニングツリーのコンテキストでは、バックエッジはノードxの子孫を祖先xに接続するリンクです。

partial ADAG: A subset of an Almost Directed Acyclic Graph (ADAG) that doesn't yet contain all the nodes in the block. A partial ADAG is created during the MRT Lowpoint algorithm and then expanded until all nodes in the block are included and it becomes an ADAG.

部分ADAG:ブロック内のすべてのノードをまだ含んでいない、Almost Directed Acyclic Graph(ADAG)のサブセット。部分的なADAGはMRTローポイントアルゴリズム中に作成され、ブロック内のすべてのノードが含まれてADAGになるまで拡張されます。

DFS: Depth-First Search DFS ancestor: A node n is a DFS ancestor of x if n is on the DFS-tree path from the DFS root to x.

DFS:深さ優先検索DFS祖先:nがDFSルートからxへのDFSツリーパス上にある場合、ノードnはxのDFS祖先です。

DFS descendant: A node n is a DFS descendant of x if x is on the DFS-tree path from the DFS root to n.

DFS子孫:xがDFSルートからnへのDFSツリーパス上にある場合、ノードnはxのDFS子孫です。

ear: A path along nodes that are not yet included in the Generalized ADAG (GADAG) that starts at a node that is already included in the GADAG and that ends at a node that is already included in the GADAG. The starting and ending nodes may be the same node if it is a cut-vertex.

耳:まだGADAGに含まれているノードで始まり、GADAGにすでに含まれているノードで終わる、一般化ADAG(GADAG)にまだ含まれていないノードに沿ったパス。頂点のカットの場合、開始ノードと終了ノードは同じノードである可能性があります。

X>>Y or Y<<X: Indicates the relationship between X and Y in a partial order, such as found in a GADAG. X>>Y means that X is higher in the partial order than Y. Y<<X means that Y is lower in the partial order than X.

X >> YまたはY << X:GADAGのように、XとYの関係を半順序で示します。 X >> Yは、XがYよりも部分的な順序で高いことを意味します。Y<< Xは、YがXよりも部分的な順序で低いことを意味します。

X>Y or Y<X: Indicates the relationship between X and Y in the total order, such as found via a topological sort. X>Y means that X is higher in the total order than Y. Y<X means that Y is lower in the total order than X.

X> YまたはY <X:トポロジーソートを介して検出されるなど、XとYの間の全体の順序の関係を示します。 X> Yは、XがYよりも全体の順序で高いことを意味します。Y<Xは、YがXよりも全体の順序で低いことを意味します。

X ?? Y: Indicates that X is unordered with respect to Y in the partial order.

バツ ?? Y:XがYに対して半順序で順序付けされていないことを示します。

UNDIRECTED: In the GADAG, each link is marked as OUTGOING, INCOMING, or both. Until the directionality of the link is determined, the link is marked as UNDIRECTED to indicate that its direction hasn't been determined.

無向:GADAGでは、各リンクはOUTGOING、INCOMING、またはその両方としてマークされます。リンクの方向性が決定されるまで、リンクはUNDIRECTEDとしてマークされ、方向が決定されていないことを示します。

OUTGOING: A link marked as OUTGOING has direction in the GADAG from the interface's router to the remote end.

OUTGOING:OUTGOINGとマークされたリンクは、インターフェイスのルーターからリモートエンドへのGADAGの方向を持っています。

INCOMING: A link marked as INCOMING has direction in the GADAG from the remote end to the interface's router.

INCOMING:INCOMINGとマークされたリンクは、GADAGでリモートエンドからインターフェイスのルーターへの方向を示します。

4. Algorithm Key Concepts
4. アルゴリズムの主要な概念

There are five key concepts that are critical for understanding the MRT Lowpoint algorithm. The first is the idea of partially ordering the nodes in a network graph with regard to each other and to the GADAG root. The second is the idea of finding an ear of nodes and adding them in the correct direction. The third is the idea of a Lowpoint value and how it can be used to identify cut-vertices and to find a second path towards the root. The fourth is the idea that a non-2-connected graph is made up of blocks, where a block is a 2-connected cluster, a cut-link or an isolated node. The fifth is the idea of a localroot for each node; this is used to compute ADAGs in each block.

MRTローポイントアルゴリズムを理解するには、5つの重要な概念があります。 1つ目は、ネットワークグラフ内のノードを相互に、およびGADAGルートに対して部分的に順序付けるという考え方です。 2つ目は、ノードの耳を見つけ、それらを正しい方向に追加するという考え方です。 3番目は、Lowpoint値の考え方と、それを使用してカット頂点を識別し、ルートへの2番目のパスを見つける方法です。 4番目は、2結合されていないグラフがブロックで構成されているという考えです。ブロックは、2結合されたクラスター、カットリンク、または孤立したノードです。 5番目は、各ノードのローカルルートのアイデアです。これは、各ブロックのADAGを計算するために使用されます。

4.1. Partial Ordering for Disjoint Paths
4.1. 素なパスの部分的な順序付け

Given any two nodes X and Y in a graph, a particular total order means that either X<Y or X>Y in that total order. An example would be a graph where the nodes are ranked based upon their unique IP loopback addresses. In a partial order, there may be some nodes for which it can't be determined whether X<<Y or X>>Y. A partial order can be captured in a directed graph, as shown in Figure 3. In a graphical representation, a link directed from X to Y indicates that X is a neighbor of Y in the network graph and X<<Y.

グラフ内の2つのノードXとYが与えられた場合、特定の合計順序は、その合計順序でX <YまたはX> Yのいずれかであることを意味します。例は、一意のIPループバックアドレスに基づいてノードがランク付けされるグラフです。一部の順序では、X << YであるかX >> Yであるかを判別できないノードが存在する可能性があります。部分的な順序は、図3に示すように、有向グラフでキャプチャできます。グラフ表現では、XからYへのリンクは、XがネットワークグラフのYの隣接であり、X << Yであることを示します。

         [A]<---[R]    [E]       R << A << B << C << D << E
          |             ^        R << A << B << F << G << H << D << E
          |             |
          V             |        Unspecified Relationships:
         [B]--->[C]--->[D]             C and F
          |             ^              C and G
          |             |              C and H
          V             |
         [F]--->[G]--->[H]
        

Figure 3: Directed Graph Showing a Partial Order

図3:部分的な順序を示す有向グラフ

To compute MRTs, the root of the MRTs is at both the very bottom and the very top of the partial ordering. This means that from any node X, one can pick nodes higher in the order until the root is reached. Similarly, from any node X, one can pick nodes lower in the order until the root is reached. For instance, in Figure 4, from G the higher nodes picked can be traced by following the directed links and are H, D, E, and R. Similarly, from G the lower nodes picked can be traced by reversing the directed links and are F, B, A, and R. A graph that represents this modified partial order is no longer a DAG; it is termed an Almost DAG (ADAG) because if the links directed to the root were removed, it would be a DAG.

MRTを計算するために、MRTのルートは、部分的な順序付けの最下部と最上部の両方にあります。つまり、任意のノードXから、ルートに到達するまで上位のノードを選択できます。同様に、任意のノードXから、ルートに到達するまで下位のノードを選択できます。たとえば、図4では、Gから選択された上位ノードは、有向リンクをたどることによってトレースでき、H、D、E、およびRです。同様に、Gから選択された下位ノードは、有向リンクを逆にすることでトレースできます。 F、B、A、およびR。この変更された半順序を表すグラフは、DAGではなくなりました。ルートへのリンクが削除された場合はDAGになるため、Almost DAG(ADAG)と呼ばれます。

     [A]<---[R]<---[E]      R << A << B << C << R
      |      ^      ^       R << A << B << C << D << E << R
      |      |      |       R << A << B << F << G << H << D << E << R
      V      |      |
     [B]--->[C]--->[D]      Unspecified Relationships:
      |             ^              C and F
      |             |              C and G
      V             |              C and H
     [F]--->[G]--->[H]
        

Figure 4: ADAG Showing a Partial Order with R Lowest and Highest

図4:Rが最低および最高の部分的な順序を示すADAG

Most importantly, if a node Y>>X, then Y can only appear on the increasing path from X to the root and never on the decreasing path. Similarly, if a node Z<<X, then Z can only appear on the decreasing path from X to the root and never on the increasing path.

最も重要なのは、ノードY >> Xの場合、YはXからルートへの増加するパスにのみ出現し、減少するパスには出現しないことです。同様に、ノードZ << Xの場合、ZはXからルートへの減少するパスにのみ表示され、増加するパスには表示されません。

When following the increasing paths, it is possible to pick multiple higher nodes and still have the certainty that those paths will be disjoint from the decreasing paths. For example, in the previous example, node B has multiple possibilities to forward packets along an increasing path: it can either forward packets to C or F.

増加するパスをたどるとき、複数のより高いノードを選択することが可能であり、それらのパスが減少するパスから切り離されるという確実性をまだ持っています。たとえば、前の例では、ノードBには、増加するパスに沿ってパケットを転送する複数の可能性があります。ノードBは、パケットをCまたはFに転送できます。

4.2. Finding an Ear and the Correct Direction
4.2. 耳と正しい方向を見つける

For simplicity, the basic idea of creating a GADAG by adding ears is described assuming that the network graph is a single 2-connected cluster so that an ADAG is sufficient. Generalizing to multiple blocks is done by considering the block-roots instead of the GADAG root -- and the actual algorithm is given in Section 5.5.

簡単にするために、耳を追加してGADAGを作成する基本的な考え方は、ADAGで十分であるようにネットワークグラフが2つの接続された単一のクラスターであると想定して説明されています。複数のブロックへの一般化は、GADAGルートの代わりにブロックルートを考慮することによって行われます。実際のアルゴリズムはセクション5.5に示されています。

In order to understand the basic idea of finding an ADAG, first suppose that we have already a partial ADAG, which doesn't contain all the nodes in the block yet, and we want to extend it to cover all the nodes. Suppose that we find a path from a node X to Y such that X and Y are already contained by our partial ADAG, but all the remaining nodes along the path are not added to the ADAG yet. We refer to such a path as an "ear".

ADAGを見つける基本的な考え方を理解するために、最初に、ブロック内のすべてのノードをまだ含んでいない部分的なADAGがあり、それを拡張してすべてのノードをカバーするとします。ノードXからYへのパスが見つかり、XとYがすでに部分ADAGに含まれているが、パスに沿った残りのすべてのノードはまだADAGに追加されていないとします。このような経路を「耳」と呼びます。

Recall that our ADAG is closely related to a partial order. More precisely, if we remove root R, the remaining DAG describes a partial order of the nodes. If we suppose that neither X nor Y is the root, we may be able to compare them. If one of them is definitely lesser with respect to our partial order (say X<<Y), we can add the new path to the ADAG in a direction from X to Y. As an example, consider Figure 5.

ADAGは半順序と密接に関連していることを思い出してください。より正確には、ルートRを削除すると、残りのDAGはノードの部分的な順序を示します。 XもYもルートではないと仮定すると、それらを比較できる可能性があります。それらの1つが部分的な順序(X << Yなど)に比べて明らかに小さい場合、XからYの方向にADAGへの新しいパスを追加できます。例として、図5を検討してください。

           E---D---|              E<--D---|           E<--D<--|
           |   |   |              |   ^   |           |   ^   |
           |   |   |              V   |   |           V   |   |
           R   F   C              R   F   C           R   F   C
           |   |   |              |   ^   |           |   ^   ^
           |   |   |              V   |   |           V   |   |
           A---B---|              A-->B---|           A-->B---|
        

(a) (b) (c)

(a)(b)(c)

(a) A 2-connected graph (b) Partial ADAG (C is not included) (c) Resulting ADAG after adding path (or ear) B-C-D

(a)2連結グラフ(b)部分的なADAG(Cは含まれていません)(c)パス(または耳)を追加した後の結果のADAG B-C-D

Figure 5

図5

In this partial ADAG, node C is not yet included. However, we can find path B-C-D, where both endpoints are contained by this partial ADAG (we say those nodes are "ready" in the following text), and the remaining node (node C) is not contained yet. If we remove R, the remaining DAG defines a partial order, and with respect to this partial order, we can say that B<<D; so, we can add the path to the ADAG in the direction from B to D (arcs B->C and C->D are added). If B>>D, we would add the same path in reverse direction.

この部分的なADAGでは、ノードCはまだ含まれていません。ただし、パスB-C-Dを見つけることができます。この場合、両方のエンドポイントがこの部分的なADAGに含まれており(これらのノードは次のテキストでは「準備完了」です)、残りのノード(ノードC)はまだ含まれていません。 Rを削除すると、残りのDAGは半順序を定義します。この半順序に関して、B << Dと言えます。そのため、BからDの方向にADAGへのパスを追加できます(弧B-> CおよびC-> Dが追加されます)。 B >> Dの場合、同じパスを逆方向に追加します。

If, in the partial order where an ear's two ends are X and Y, X<<Y, then there must already be a directed path from X to Y in the ADAG. The ear must be added in a direction such that it doesn't create a cycle; therefore, the ear must go from X to Y.

耳の両端がXとYである部分的な順序でX << Yの場合、ADAGにはXからYへの有向パスがすでに存在している必要があります。耳は、それがサイクルを作成しないような方向に追加する必要があります。したがって、耳はXからYに移動する必要があります。

In the case when X and Y are not ordered with each other, we can select either direction for the ear. We have no restriction since neither of the directions can result in a cycle. In the corner case when one of the endpoints of an ear, say X, is the root (recall that the two endpoints must be different), we could use both directions again for the ear because the root can be considered both as smaller and as greater than Y. However, we strictly pick that direction in which the root is lower than Y. The logic for this decision is explained in Section 5.7

XとYが互いに順序付けられていない場合は、耳のどちらの方向も選択できます。どちらの方向も循環を引き起こさないため、制限はありません。耳の端点の1つ、たとえばXがルートである(2つの端点は異なる必要があることを思い出してください)コーナーケースでは、ルートを小さくすることも、 Yよりも大きい。ただし、ルートがYよりも低い方向を厳密に選択します。この決定のロジックについては、セクション5.7で説明します。

A partial ADAG is started by finding a cycle from the root R back to itself. This can be done by selecting a non-ready neighbor N of R and then finding a path from N to R that doesn't use any links between R and N. The direction of the cycle can be assigned either way since it is starting the ordering.

部分的なADAGは、ルートRから自分自身に戻るサイクルを見つけることから始まります。これは、Rの準備ができていない隣接Nを選択し、RとNの間のリンクを使用しないNからRへのパスを見つけることで実行できます。サイクルの方向は、注文。

Once a partial ADAG is already present, it will always have a node that is not the root R in it. The following is a brief proof that a partial ADAG can always have ears added to it: just select a non-ready neighbor N of a ready node Q, such that Q is not the root R, find a path from N to the root R in the graph with Q removed. This path is an ear where the first node of the ear is Q, the next is N, then the path until the first ready node the path reached (that ready node is the other endpoint of the path). Since the graph is 2-connected, there must be a path from N to R without Q.

部分的なADAGが既に存在している場合は、ルートRではないノードが常に存在します。以下は、部分的なADAGに常に耳を追加できることの簡単な証明です:QがルートRではないように、準備完了ノードQの準備ができていない隣接Nを選択し、NからルートRへのパスを見つけますQを削除したグラフ。このパスは、耳の最初のノードがQ、次がN、次にパスが到達した最初の作動可能ノードまでのパスです(その作動可能ノードはパスのもう一方のエンドポイントです)。グラフは2連結なので、QなしでNからRへのパスが必要です。

It is always possible to select a non-ready neighbor N of a ready node Q so that Q is not the root R. Because the network is 2-connected, N must be connected to two different nodes and only one can be R. Because the initial cycle has already been added to the ADAG, there are ready nodes that are not R. Since the graph is 2-connected, while there are non-ready nodes, there must be a non-ready neighbor N of a ready node that is not R.

QがルートRにならないように、準備完了ノードQの準備ができていない隣接ノードNを常に選択することが可能です。ネットワークは2つ接続されているため、Nは2つの異なるノードに接続する必要があり、Rにできるのは1つだけです。最初のサイクルが既にADAGに追加されている場合、Rではない準備ノードが存在します。グラフが2接続されているため、準備ができていないノードがある一方で、準備ができているノードの準備ができていないノードの近隣Nが存在する必要がありますRではありません

Generic_Find_Ears_ADAG(root) Create an empty ADAG. Add root to the ADAG. Mark root as IN_GADAG. Select an arbitrary cycle containing root. Add the arbitrary cycle to the ADAG. Mark cycle's nodes as IN_GADAG. Add cycle's non-root nodes to process_list. While there exist connected nodes in graph that are not IN_GADAG Select a new ear. Let its endpoints be X and Y. If Y is root or (Y<<X) Add the ear towards X to the ADAG Else // (a) X is root, or (b) X<<Y, or (c) X, Y not ordered Add the ear towards Y to the ADAG

Generic_Find_Ears_ADAG(root)空のADAGを作成します。 ADAGにルートを追加します。ルートをIN_GADAGとしてマークします。ルートを含む任意のサイクルを選択します。 ADAGに任意のサイクルを追加します。サイクルのノードをIN_GADAGとしてマークします。サイクルの非ルートノードをprocess_listに追加します。 IN_GADAGではないグラフに接続されたノードが存在する間、新しい耳を選択します。エンドポイントをXおよびYとします。Yがルートまたは(Y << X)の場合、耳をXに向けてADAGに追加します。 X、Yは注文されていませんYに向かって耳をADAGに追加します

Figure 6: Generic Algorithm to Find Ears and Their Direction in 2-Connected Graph

図6:2連結グラフで耳とその方向を見つける一般的なアルゴリズム

The algorithm in Figure 6 merely requires that a cycle or ear be selected without specifying how. Regardless of the method for selecting the path, we will get an ADAG. The method used for finding and selecting the ears is important; shorter ears result in shorter paths along the MRTs. The MRT Lowpoint algorithm uses the Lowpoint Inheritance method for constructing an ADAG (and ultimately a GADAG). This method is defined in Section 5.5. Other methods for constructing GADAGs are described in Appendices B and C. An evaluation of these different methods is given in Section 8.

図6のアルゴリズムでは、方法を指定せずにサイクルまたは耳を選択するだけです。パスの選択方法に関係なく、ADAGを取得します。耳を見つけて選択する方法は重要です。耳が短いほど、MRTに沿った経路が短くなります。 MRTローポイントアルゴリズムは、ADAG(最終的にはGADAG)を構築するためにローポイント継承メソッドを使用します。このメソッドはセクション5.5で定義されています。 GADAGを作成する他の方法については、付録BおよびCで説明します。これらの異なる方法の評価については、セクション8で説明します。

As an example, consider Figure 5 again. First, we select the shortest cycle containing R, which can be R-A-B-F-D-E (uniform link costs were assumed), so we get to the situation depicted in Figure 5(b). Finally, we find a node next to a ready node; that must be node C and assume we reached it from ready node B. We search a path from C to R without B in the original graph. The first ready node along this is node D, so the open ear is B-C-D. Since B<<D, we add arc B->C and C->D to the ADAG. Since all the nodes are ready, we stop at this point.

例として、図5をもう一度考えてみます。最初に、Rを含む最短のサイクルを選択します。これはR-A-B-F-D-E(均一なリンクコストが想定されます)になる可能性があるため、図5(b)に示す状況になります。最後に、準備完了ノードの隣にノードを見つけます。これはノードCでなければならず、準備ができたノードBから到達したと想定しています。元のグラフで、CからBなしのRへのパスを検索します。これに沿った最初の準備完了ノードはノードDなので、開いた耳はB-C-Dです。 B << Dなので、アークB-> CおよびC-> DをADAGに追加します。すべてのノードの準備が整っているので、ここで停止します。

4.3. Lowpoint Values and Their Uses
4.3. 低点値とその用途

A basic way of computing a spanning tree on a network graph is to run a DFS, such as given in Figure 7. This tree has the important property that if there is a link (x, n), then either n is a DFS ancestor of x or n is a DFS descendant of x. In other words, either n is on the path from the root to x or x is on the path from the root to n.

ネットワークグラフ上のスパニングツリーを計算する基本的な方法は、図7に示すように、DFSを実行することです。このツリーには、リンク(x、n)がある場合、いずれかのnがDFS祖先であるという重要な特性があります。 of xまたはnは、xのDFS子孫です。つまり、nはルートからxへのパス上にあるか、xはルートからnへのパス上にあります。

global_variable: dfs_number

global_variable:dfs_number

DFS_Visit(node x, node parent) D(x) = dfs_number dfs_number += 1 x.dfs_parent = parent for each link (x, w) if D(w) is not set DFS_Visit(w, x)

DFS_Visit(ノードx、ノードの親)D(x)= dfs_number dfs_number + = 1 x.dfs_parent = D(w)が設定されていない場合、各リンクの親(x、w)DFS_Visit(w、x)

Run_DFS(node gadag_root) dfs_number = 0 DFS_Visit(gadag_root, NONE)

Run_DFS(ノードgadag_root)dfs_number = 0 DFS_Visit(gadag_root、NONE)

Figure 7: Basic DFS Algorithm

図7:基本的なDFSアルゴリズム

Given a node x, one can compute the minimal DFS number of the neighbors of x, i.e., min( D(w) if (x,w) is a link). This gives the earliest attachment point neighboring x. What is interesting, though, is the earliest attachment point from x and x's descendants. This is what is determined by computing the Lowpoint value.

ノードxが与えられると、xの近傍の最小DFS数、つまりmin(D(w)if(x、w)is a link)を計算できます。これにより、xに隣接する最も早い接続点が得られます。しかし興味深いのは、xとxの子孫からの最初の接続点です。これは、ローポイント値を計算することによって決定されます。

In order to compute the low point value, the network is traversed using DFS and the vertices are numbered based on the DFS walk. Let this number be represented as DFS(x). All the edges that lead to already-visited nodes during DFS walk are back-edges. The back-edges are important because they give information about reachability of a node via another path.

低いポイント値を計算するために、ネットワークはDFSを使用してトラバースされ、DFSウォークに基づいて頂点に番号が付けられます。この数をDFS(x)として表します。 DFSウォーク中にすでにアクセスされたノードにつながるすべてのエッジはバックエッジです。バックエッジは、別のパスを介したノードの到達可能性に関する情報を提供するため、重要です。

The low point number is calculated by finding:

低ポイント数は、以下を検索して計算されます。

Low(x) = Minimum of ( (DFS(x), Lowest DFS(n, x->n is a back-edge), Lowest Low(n, x->n is tree edge in DFS walk) ).

Low(x)=最小値((DFS(x)、最も低いDFS(n、x-> nはバックエッジ))、最も低い(n、x-> nはDFSウォークのツリーエッジ))。

A detailed algorithm for computing the lowpoint value is given in Figure 8. Figure 9 illustrates how the Lowpoint algorithm applies to an example graph.

ローポイント値を計算するための詳細なアルゴリズムを図8に示します。図9は、ローポイントアルゴリズムがグラフの例にどのように適用されるかを示しています。

global_variable: dfs_number

global_variable:dfs_number

            Lowpoint_Visit(node x, node parent, interface p_to_x)
               D(x) = dfs_number
               L(x) = D(x)
               dfs_number += 1
               x.dfs_parent = parent
               x.dfs_parent_intf = p_to_x.remote_intf
               x.lowpoint_parent = NONE
               for each ordered_interface intf of x
                 if D(intf.remote_node) is not set
                   Lowpoint_Visit(intf.remote_node, x, intf)
                   if L(intf.remote_node) < L(x)
                      L(x) = L(intf.remote_node)
                      x.lowpoint_parent = intf.remote_node
                      x.lowpoint_parent_intf = intf
                 else if intf.remote_node is not parent
                   if D(intf.remote_node) < L(x)
                      L(x) = D(intf.remote_node)
                      x.lowpoint_parent = intf.remote_node
                      x.lowpoint_parent_intf = intf
        

Run_Lowpoint(node gadag_root) dfs_number = 0 Lowpoint_Visit(gadag_root, NONE, NONE)

Run_Lowpoint(node gadag_root)dfs_number = 0 Lowpoint_Visit(gadag_root、NONE、NONE)

Figure 8: Computing Lowpoint Value

図8:ローポイント値の計算

            [E]---|    [J]-------[I]   [P]---[O]
             |    |     |         |     |     |
             |    |     |         |     |     |
            [R]  [D]---[C]--[F]  [H]---[K]   [N]
             |          |    |    |     |     |
             |          |    |    |     |     |
            [A]--------[B]  [G]---|    [L]---[M]
        

(a) a non-2-connected graph

(a)2連結でないグラフ

             [E]----|    [J]---------[I]    [P]------[O]
            (5, )   |  (10, )       (9, ) (16,  ) (15,  )
              |     |     |           |      |        |
              |     |     |           |      |        |
             [R]   [D]---[C]---[F]   [H]----[K]      [N]
            (0, ) (4, ) (3, ) (6, ) (8, ) (11, )  (14, )
              |           |     |     |      |        |
              |           |     |     |      |        |
             [A]---------[B]   [G]----|     [L]------[M]
            (1, )       (2, ) (7, )       (12,  )  (13,  )
        

(b) with DFS values assigned (D(x), L(x))

(b)DFS値が割り当てられている(D(x)、L(x))

             [E]----|    [J]---------[I]    [P]------[O]
            (5,0)   |  (10,3)       (9,3) (16,11) (15,11)
              |     |     |           |      |        |
              |     |     |           |      |        |
             [R]   [D]---[C]---[F]   [H]----[K]      [N]
            (0,0) (4,0) (3,0) (6,3) (8,3) (11,11) (14,11)
              |           |     |     |      |        |
              |           |     |     |      |        |
             [A]---------[B]   [G]----|     [L]------[M]
            (1,0)       (2,0) (7,3)       (12,11)  (13,11)
        

(c) with lowpoint values assigned (D(x), L(x))

(c)低点値が割り当てられている(D(x)、L(x))

Figure 9: Example Lowpoint Value Computation

図9:低点値計算の例

From the lowpoint value and lowpoint parent, there are three very useful things that motivate our computation.

低点値と低点親から、計算の動機となる3つの非常に有用なものがあります。

First, if there is a child c of x such that L(c) >= D(x), then there are no paths in the network graph that go from c or its descendants to an ancestor of x; therefore, x is a cut-vertex. In Figure 9, this can be seen by looking at the DFS children of C. C has two children, D and F and L(F) = 3 = D(C); so, it is clear that C is a cut-vertex and F is in a block where C is the block's root. L(D) = 0<3 = D(C), so D has a path to the ancestors of C; in this case, D can go via E to reach R. Comparing the lowpoint values of all a node's DFS-children with the node's DFS-value is very useful because it allows identification of the cut-vertices and thus the blocks.

まず、L(c)> = D(x)であるようなxの子cがある場合、cまたはその子孫からxの祖先に至るネットワークグラフ内のパスはありません。したがって、xはカット頂点です。図9では、これはCのDFS子を見るとわかります。Cには2つの子DとFがあり、L(F)= 3 = D(C);です。したがって、Cがカット頂点であり、Fがブロック内にあることは明らかです。Cはブロックのルートです。 L(D)= 0 <3 = D(C)なので、DにはCの祖先へのパスがあります。この場合、DはEを経由してRに到達できます。すべてのノードのDFS子の低点値をノードのDFS値と比較すると、カット頂点とブロックを識別できるため、非常に役立ちます。

Second, by repeatedly following the path given by lowpoint_parent, there is a path from x back to an ancestor of x that does not use the link [x, x.dfs_parent] in either direction. The full path need not be taken, but this gives a way of finding an initial cycle and then ears.

次に、lowpoint_parentで指定されたパスを繰り返したどることにより、xからxの祖先に戻るパスがあり、どちらの方向にもリンク[x、x.dfs_parent]を使用しません。完全なパスをとる必要はありませんが、これは最初のサイクルを見つけ、次に耳を見つける方法を提供します。

Third, as seen in Figure 9, even if L(x)<D(x), there may be a block that contains both the root and a DFS-child of a node while other DFS-children might be in different blocks. In this example, C's child D is in the same block as R while F is not. It is important to realize that the root of a block may also be the root of another block.

3番目に、図9に示すように、L(x)<D(x)の場合でも、ノードのルートとDFS子の両方を含むブロックがあり、他のDFS子が異なるブロックにある場合があります。この例では、Cの子DはRと同じブロックにありますが、Fはそうではありません。ブロックのルートが別のブロックのルートになることもあることを認識することが重要です。

4.4. Blocks in a Graph
4.4. グラフのブロック

A key idea for the MRT Lowpoint algorithm is that any non-2-connected graph is made up by blocks (e.g., 2-connected clusters, cut-links, and/or isolated nodes). To compute GADAGs and thus MRTs, computation is done in each block to compute ADAGs or Redundant Trees and then those ADAGs or Redundant Trees are combined into a GADAG or MRT.

MRTローポイントアルゴリズムの重要なアイデアは、2に接続されていないグラフはブロック(2に接続されたクラスター、カットリンク、分離されたノードなど)で構成されるということです。 GADAG、つまりMRTを計算するには、各ブロックでADAGまたは冗長ツリーを計算してから、それらのADAGまたは冗長ツリーをGADAGまたはMRTに結合します。

                  [E]---|    [J]-------[I]   [P]---[O]
                   |    |     |         |     |     |
                   |    |     |         |     |     |
                  [R]  [D]---[C]--[F]  [H]---[K]   [N]
                   |          |    |    |     |     |
                   |          |    |    |     |     |
                  [A]--------[B]  [G]---|    [L]---[M]
        

(a) A graph with four blocks: three 2-connected clusters and one cut-link

(a)4つのブロックを持つグラフ:2つの接続された3つのクラスターと1つのカットリンク

                  [E]<--|    [J]<------[I]   [P]<--[O]
                   |    |     |         ^     |     ^
                   V    |     V         |     V     |
                  [R]  [D]<--[C]  [F]  [H]<---[K]  [N]
                              ^    |    ^           ^
                              |    V    |           |
                  [A]------->[B]  [G]---|     [L]-->[M]
        

(b) MRT-Blue for destination R

(b)宛先RのMRT-Blue

                  [E]---|    [J]-------->[I]    [P]-->[O]
                        |                 |            |
                        V                 V            V
                  [R]  [D]-->[C]<---[F]  [H]<---[K]   [N]
                   ^          |      ^    |      ^     |
                   |          V      |    |      |     V
                  [A]<-------[B]    [G]<--|     [L]<--[M]
        

(c) MRT-Red for destination R

(c)宛先RのMRT-Red

Figure 10

図10

Consider the example depicted in Figure 10 (a). In this figure, a special graph is presented, showing us all the ways 2-connected clusters can be connected. It has four blocks: block 1 contains R, A, B, C, D, E; block 2 contains C, F, G, H, I, J; block 3 contains K, L, M, N, O, P; and block 4 is a cut-link containing H and K. As can be observed, the first two blocks have one common node (node C) and blocks 2 and 3 do not have any common node, but they are connected through a cut-link that is block 4. No two blocks can have more than one common node, since two blocks with at least two common nodes would qualify as a single 2-connected cluster.

図10(a)の例を考えてみます。この図では、2つの接続されたクラスターを接続できるすべての方法を示す特別なグラフが示されています。 4つのブロックがあります。ブロック1にはR、A、B、C、D、Eが含まれています。ブロック2にはC、F、G、H、I、Jが含まれます。ブロック3には、K、L、M、N、O、Pが含まれます。ブロック4はHとKを含むカットリンクです。最初の2つのブロックには1つの共通ノード(ノードC)があり、ブロック2と3には共通ノードがありませんが、これらはカットリンクはブロック4です。少なくとも2つの共通ノードを持つ2つのブロックは、単一の2接続されたクラスターと見なされるため、2つのブロックが複数の共通ノードを持つことはできません。

Moreover, observe that if we want to get from one block to another, we must use a cut-vertex (the cut-vertices in this graph are C, H, K), regardless of the path selected, so we can say that all the paths from block 3 along the MRTs rooted at R will cross K first. This observation means that if we want to find a pair of MRTs rooted at R, then we need to build up a pair of RTs in block 3 with K as a root. Similarly, we need to find another pair of RTs in block 2 with C as a root, and finally, we need the last pair of RTs in block 1 with R as a root. When all the trees are selected, we can simply combine them; when a block is a cut-link (as in block 4), that cut-link is added in the same direction to both of the trees. The resulting trees are depicted in Figure 10 (b) and (c).

さらに、あるブロックから別のブロックに移動する場合は、選択したパスに関係なく、カット頂点(このグラフのカット頂点はC、H、K)を使用する必要があることに注意してください。 RをルートとするMRTに沿ったブロック3からのパスは、最初にKを通過します。この観察は、RをルートとするMRTのペアを見つけたい場合、Kをルートとして、ブロック3でRTのペアを構築する必要があることを意味します。同様に、Cをルートとするブロック2のRTの別のペアを見つける必要があり、最後に、Rをルートとするブロック1の最後のRTペアが必要です。すべてのツリーを選択したら、それらを単純に組み合わせることができます。ブロックが(ブロック4のように)カットリンクである場合、そのカットリンクは両方のツリーに同じ方向で追加されます。結果のツリーを図10(b)および(c)に示します。

Similarly, to create a GADAG it is sufficient to compute ADAGs in each block and connect them.

同様に、GADAGを作成するには、各ブロックのADAGを計算して接続するだけで十分です。

It is necessary, therefore, to identify the cut-vertices, the blocks and identify the appropriate localroot to use for each block.

したがって、カット頂点、ブロックを特定し、各ブロックに使用する適切なローカルルートを特定する必要があります。

4.5. Determining Localroot and Assigning Block-ID
4.5. ローカルルートの決定とブロックIDの割り当て

Each node in a network graph has a localroot, which is the cut-vertex (or root) in the same block that is closest to the root. The localroot is used to determine whether two nodes share a common block.

ネットワークグラフの各ノードにはローカルルートがあります。これは、ルートに最も近い同じブロック内のカット頂点(またはルート)です。 localrootは、2つのノードが共通ブロックを共有しているかどうかを判別するために使用されます。

Compute_Localroot(node x, node localroot) x.localroot = localroot for each DFS child node c of x if L(c) < D(x) //x is not a cut-vertex Compute_Localroot(c, x.localroot) else mark x as cut-vertex Compute_Localroot(c, x)

Compute_Localroot(node x、node localroot)x.localroot = localroot = xの各DFS子ノードcの場合L(c)<D(x)// xはカット頂点ではないCompute_Localroot(c、x.localroot)elseマークカット頂点としてのx Compute_Localroot(c、x)

Compute_Localroot(gadag_root, gadag_root)

Compute_Localroot(gadag_root、gadag_root)

Figure 11: A Method for Computing Localroots

図11:ローカルルートを計算する方法

There are two different ways of computing the localroot for each node. The stand-alone method is given in Figure 11 and better illustrates the concept; it is used by the GADAG construction methods given in Appendices B and C. The MRT Lowpoint algorithm computes the localroot for a block as part of computing the GADAG using lowpoint inheritance; the essence of this computation is given in Figure 12. Both methods for computing the localroot produce the same results.

各ノードのローカルルートを計算するには、2つの異なる方法があります。スタンドアロンの方法を図11に示し、概念をよりよく示しています。付録BおよびCに記載されているGADAG構築メソッドで使用されます。MRTローポイントアルゴリズムは、ローポイント継承を使用したGADAGの計算の一部として、ブロックのローカルルートを計算します。この計算の本質を図12に示します。ローカルルートを計算する両方の方法で同じ結果が得られます。

Get the current node, s. Compute an ear (either through lowpoint inheritance or by following dfs parents) from s to a ready node e. (Thus, s is not e, if there is such ear.) if s is e for each node x in the ear that is not s x.localroot = s else for each node x in the ear that is not s or e x.localroot = e.localroot

現在のノードsを取得します。 sから準備完了ノードeへの(低点継承によるか、またはdfsの親に従うことによる)耳を計算します。 (したがって、そのような耳が存在する場合、sはeではありません。)sが耳内の各ノードxに対してeであり、sでない場合。x.localroot = s耳内の各ノードxに対して、sまたはe xでない場合.localroot = e.localroot

Figure 12: Ear-Based Method for Computing Localroots

図12:ローカルルートを計算するための耳ベースの方法

Once the localroots are known, two nodes X and Y are in a common block if and only if one of the following three conditions apply.

ローカルルートが判明すると、次の3つの条件のいずれかが当てはまる場合にのみ、2つのノードXとYが共通ブロックに入ります。

o Y's localroot is X's localroot : They are in the same block and neither is the cut-vertex closest to the root.

o YのローカルルートはXのローカルルートです。これらは同じブロックにあり、ルートに最も近いカット頂点でもありません。

o Y's localroot is X: X is the cut-vertex closest to the root for Y's block

o YのローカルルートはX:XはYのブロックのルートに最も近いカット頂点

o Y is X's localroot: Y is the cut-vertex closest to the root for X's block

o YはXのローカルルートです:YはXのブロックのルートに最も近いカット頂点です

Once we have computed the localroot for each node in the network graph, we can assign for each node, a Block-ID that represents the block in which the node is present. This computation is shown in Figure 13.

ネットワークグラフの各ノードのローカルルートを計算したら、ノードが存在するブロックを表すBlock-IDを各ノードに割り当てることができます。この計算を図13に示します。

global_var: max_block_id

global_var:max_block_id

Assign_Block_ID(x, cur_block_id) x.block_id = cur_block_id foreach DFS child c of x if (c.local_root is x) max_block_id += 1 Assign_Block_ID(c, max_block_id) else Assign_Block_ID(c, cur_block_id)

Assign_Block_ID(x、cur_block_id)x.block_id = cur_block_id foreach DFS child x of x if(c.local_root is x)max_block_id + = 1 Assign_Block_ID(c、max_block_id)else Assign_Block_ID(c、cur_block_id)

max_block_id = 0 Assign_Block_ID(gadag_root, max_block_id)

max_block_id = 0 Assign_Block_ID(gadag_root、max_block_id)

Figure 13: Assigning Block-ID to Identify Blocks

図13:ブロックを識別するためのブロックIDの割り当て

5. MRT Lowpoint Algorithm Specification
5. MRTローポイントアルゴリズムの仕様

The MRT Lowpoint algorithm computes one GADAG that is then used by a router to determine its MRT-Blue and MRT-Red next hops to all destinations. Finally, based upon that information, alternates are selected for each next hop to each destination. The different parts of this algorithm are described below.

MRTローポイントアルゴリズムは1つのGADAGを計算し、ルーターがそれを使用して、すべての宛先へのMRT-BlueおよびMRT-Redネクストホップを決定します。最後に、その情報に基づいて、各宛先への次のホップごとに代替が選択されます。このアルゴリズムのさまざまな部分について、以下で説明します。

o Order the interfaces in the network graph. See Section 5.1.

o ネットワークグラフでインターフェイスを並べ替えます。セクション5.1を参照してください。

o Compute the local MRT Island for the particular MRT Profile. See Section 5.2.

o 特定のMRTプロファイルのローカルMRTアイランドを計算します。セクション5.2を参照してください。

o Select the root to use for the GADAG. See Section 5.3.

o GADAGに使用するルートを選択します。セクション5.3を参照してください。

o Initialize all interfaces to UNDIRECTED. See Section 5.4.

o すべてのインターフェースをUNDIRECTEDに初期化します。セクション5.4を参照してください。

o Compute the DFS value, e.g., D(x), and lowpoint value, L(x). See Figure 8.

o DFS値(D(x)など)とローポイント値(L(x))を計算します。図8を参照してください。

o Construct the GADAG. See Section 5.5.

o GADAGを作成します。セクション5.5を参照してください。

o Assign directions to all interfaces that are still UNDIRECTED. See Section 5.6.

o まだ指示されていないすべてのインターフェースに方向を割り当てます。セクション5.6を参照してください。

o From the computing router x, compute the next hops for the MRT-Blue and MRT-Red. See Section 5.7.

o コンピューティングルータxから、MRT-BlueおよびMRT-Redのネクストホップを計算します。セクション5.7を参照してください。

o Identify alternates for each next hop to each destination by determining which one of the MRT-Blue and the MRT-Red the computing router x should select. See Section 5.8.

o コンピューティングルータxが選択するMRT-BlueとMRT-Redのどちらを選択するかを決定することにより、各宛先への各ネクストホップの代替を識別します。セクション5.8を参照してください。

A Python implementation of this algorithm is given in Appendix A.

このアルゴリズムのPython実装は、付録Aに記載されています。

5.1. Interface Ordering
5.1. インターフェイスの注文

To ensure consistency in computation, all routers MUST order interfaces identically down to the set of links with the same metric to the same neighboring node. This is necessary for the DFS in Lowpoint_Visit in Section 4.3, where the selection order of the interfaces to explore results in different trees. Consistent interface ordering is also necessary for computing the GADAG, where the selection order of the interfaces to use to form ears can result in different GADAGs. It is also necessary for the topological sort described in Section 5.8, where different topological sort orderings can result in undirected links being added to the GADAG in different directions.

計算の一貫性を確保するために、すべてのルーターは、同じ隣接ノードへの同じメトリックを持つリンクのセットに至るまで、同じようにインターフェイスを並べる必要があります。これは、セクション4.3のLowpoint_VisitのDFSで必要です。ここでは、インターフェイスの選択順序によって、さまざまなツリーで結果が探索されます。耳を形成するために使用するインターフェースの選択順序が異なるGADAGになる可能性がある場合、GADAGを計算するためにも一貫したインターフェースの順序が必要です。セクション5.8で説明されているトポロジカルソートの場合も必要です。トポロジソート順序が異なると、無向リンクが異なる方向でGADAGに追加される可能性があります。

The required ordering between two interfaces from the same router x is given in Figure 14.

同じルーターxの2つのインターフェース間で必要な順序を図14に示します。

Interface_Compare(interface a, interface b) if a.metric < b.metric return A_LESS_THAN_B if b.metric < a.metric return B_LESS_THAN_A if a.neighbor.mrt_node_id < b.neighbor.mrt_node_id return A_LESS_THAN_B if b.neighbor.mrt_node_id < a.neighbor.mrt_node_id return B_LESS_THAN_A // Same metric to same node, so the order doesn't matter for // interoperability. return A_EQUAL_TO_B

Interface_Compare(interface a、interface b)if a.metric <b.metric return A_LESS_THAN_B if b.metric <a.metric return B_LESS_THAN_A if a.neighbor.mrt_node_id <b.neighbor.mrt_node_id return A_LESS_THAN_B if b.neighbor.mrt_node_id .neighbor.mrt_node_id return B_LESS_THAN_A //同じメトリックが同じノードにあるため、相互運用性のために//順序は関係ありません。 A_EQUAL_TO_Bを返す

Figure 14: Rules for Ranking Multiple Interfaces (Order Is from Low to High)

図14:複数のインターフェースをランク付けするためのルール(順序は低から高)

In Figure 14, if two interfaces on a router connect to the same remote router with the same metric, the Interface_Compare function returns A_EQUAL_TO_B. This is because the order in which those interfaces are initially explored does not affect the final GADAG produced by the algorithm described here. While only one of the links will be added to the GADAG in the initial traversal, the other parallel links will be added to the GADAG with the same direction assigned during the procedure for assigning direction to UNDIRECTED links described in Section 5.6. An implementation is free to apply some additional criteria to break ties in interface ordering in this situation, but those criteria are not specified here since they will not affect the final GADAG produced by the algorithm.

図14では、ルーター上の2つのインターフェースが同じメトリックを持つ同じリモートルーターに接続している場合、Interface_Compare関数はA_EQUAL_TO_Bを返します。これは、これらのインターフェースが最初に探索される順序が、ここで説明するアルゴリズムによって生成される最終的なGADAGに影響しないためです。最初のトラバーサルでリンクの1つだけがGADAGに追加されますが、他の平行リンクは、セクション5.6で説明されているUNDIRECTEDリンクへの方向の割り当て手順中に割り当てられた同じ方向でGADAGに追加されます。実装は、この状況でのインターフェースの順序付けを断つためにいくつかの追加の基準を自由に適用できますが、それらの基準はアルゴリズムによって生成される最終的なGADAGに影響しないため、ここでは指定しません。

The Interface_Compare function in Figure 14 relies on the interface.metric and the interface.neighbor.mrt_node_id values to order interfaces. The exact source of these values for different IGPs and applications is specified in Figure 15. The metric and mrt_node_id values for OSPFv2, OSPFv3, and IS-IS provided here is normative. The metric and mrt_node_id values for IS-IS Path Control and Reservation (PCR) in this table should be considered informational. The normative values are specified in [IEEE8021Qca].

図14のInterface_Compare関数は、interface.metricおよびinterface.neighbor.mrt_node_idの値に基づいてインターフェースを注文します。さまざまなIGPおよびアプリケーションのこれらの値の正確なソースは、図15で指定されています。ここで提供されるOSPFv2、OSPFv3、およびIS-ISのメトリックおよびmrt_node_idの値は、規範的です。この表のIS-ISパス制御および予約(PCR)のメトリックとmrt_node_idの値は、情報提供と見なす必要があります。標準値は[IEEE8021Qca]で指定されています。

  +--------------+-----------------------+-----------------------------+
  | IGP/flooding | mrt_node_id           | metric of                   |
  | protocol     | of neighbor           | interface                   |
  | and          | on interface          |                             |
  | application  |                       |                             |
  +--------------+-----------------------+-----------------------------+
  | OSPFv2 for   | 4-octet Neighbor      | 2-octet Metric field        |
  | IP/LDP FRR   | Router ID in          | for corresponding           |
  |              | Link ID field for     | point-to-point link         |
  |              | corresponding         | in Router-LSA               |
  |              | point-to-point link   |                             |
  |              | in Router-LSA         |                             |
  +--------------+-----------------------+-----------------------------+
  | OSPFv3 for   | 4-octet Neighbor      | 2-octet Metric field        |
  | IP/LDP FRR   | Router ID field       | for corresponding           |
  |              | for corresponding     | point-to-point link         |
  |              | point-to-point link   | in Router-LSA               |
  |              | in Router-LSA         |                             |
  +--------------+-----------------------+-----------------------------+
  | IS-IS for    | 7-octet neighbor      | 3-octet metric field        |
  | IP/LDP FRR   | system ID and         | in Extended IS              |
  |              | pseudonode number     | Reachability TLV (type 22)  |
  |              | in Extended IS        | or Multi-Topology           |
  |              | Reachability TLV (type| IS Neighbor TLV (type 222)  |
  |              | 22) or Multi-Topology |                             |
  |              | IS Neighbor TLV (type |                             |
  |              | 222)                  |                             |
  +--------------+-----------------------+-----------------------------+
  | IS-IS PCR for| 8-octet Bridge ID     | 3-octet SPB-LINK-METRIC in  |
  | protection   | created from  2-octet | SPB-Metric sub-TLV (type 29)|
  | of traffic   | Bridge Priority in    | in Extended IS Reachability |
  | in bridged   | Shortest Path Bridging| TLV (type 22) or            |
  |              |SPB Instance sub-TLV   | Multi-Topology              |
  | networks     | (type 1) carried in   | Intermediate Systems        |
  |              | MT-Capability TLV     | TLV (type 222).  In the case|
  |              | (type 144) and 6-octet| of asymmetric link metrics, |
  |              | neighbor system ID in | the larger link metric      |
  |              | Extended IS           | is used for both link       |
  |              | Reachability TLV (type| directions.                 |
  |              | 22) or Multi-Topology | (informational)             |
  |              | Intermediate Systems  |                             |
  |              | TLV (type 222)        |                             |
  |              | (informational)       |                             |
  +--------------+-----------------------+-----------------------------+
        

Figure 15: Value of interface.neighbor.mrt_node_id and interface.metric to Be Used for Ranking Interfaces, for Different Flooding Protocols and Applications

図15:さまざまなフラッディングプロトコルおよびアプリケーションの、インターフェイスのランク付けに使用されるinterface.neighbor.mrt_node_idおよびinterface.metricの値

The metrics are unsigned integers and MUST be compared as unsigned integers. The results of mrt_node_id comparisons MUST be the same as would be obtained by converting the mrt_node_ids to unsigned integers using network byte order and performing the comparison as unsigned integers. In the case of IS-IS for IP/LDP FRR with point-to-point links, the pseudonode number (the 7th octet) is zero. Broadcast interfaces will be discussed in Section 7.

メトリックは符号なし整数であり、符号なし整数として比較する必要があります。 mrt_node_id比較の結果は、ネットワークバイトオーダーを使用してmrt_node_idsを符号なし整数に変換し、符号なし整数として比較を実行することによって得られる結果と同じでなければなりません。ポイントツーポイントリンクを使用するIS-IS for IP / LDP FRRの場合、疑似ノード番号(7番目のオクテット)はゼロです。ブロードキャストインターフェイスについては、セクション7で説明します。

5.2. MRT Island Identification
5.2. MRTアイランドの識別

The local MRT Island for a particular MRT profile can be determined by starting from the computing router in the network graph and doing a breadth-first-search (BFS). The BFS explores only links that are in the same area/level, are not IGP-excluded, and are not MRT-ineligible. The BFS explores only nodes that support the particular MRT profile. See Section 7 of [RFC7812] for more-precise definitions of these criteria.

特定のMRTプロファイルのローカルMRTアイランドは、ネットワークグラフのコンピューティングルーターから開始し、幅優先検索(BFS)を実行することで決定できます。 BFSは、同じエリア/レベルにあり、IGPから除外されておらず、MRTの対象外であるリンクのみを探索します。 BFSは、特定のMRTプロファイルをサポートするノードのみを探索します。これらの基準のより正確な定義については、[RFC7812]のセクション7を参照してください。

   MRT_Island_Identification(topology, computing_rtr, profile_id, area)
     for all routers in topology
         rtr.IN_MRT_ISLAND = FALSE
     computing_rtr.IN_MRT_ISLAND = TRUE
     explore_list = { computing_rtr }
     while (explore_list is not empty)
        next_rtr = remove_head(explore_list)
        for each intf in next_rtr
           if (not intf.IN_MRT_ISLAND
              and not intf.MRT-ineligible
              and not intf.remote_intf.MRT-ineligible
              and not intf.IGP-excluded and (intf in area)
              and (intf.remote_node supports profile_id) )
              intf.IN_MRT_ISLAND = TRUE
              intf.remote_intf.IN_MRT_ISLAND = TRUE
              if (not intf.remote_node.IN_MRT_ISLAND))
                 intf.remote_node.IN_MRT_ISLAND = TRUE
                 add_to_tail(explore_list, intf.remote_node)
        

Figure 16: MRT Island Identification

図16:MRTアイランドの識別

5.3. GADAG Root Selection
5.3. GADAGルート選択

In Section 8.3 of [RFC7812], the GADAG Root Selection Policy is described for the Default MRT Profile. This selection policy allows routers to consistently select a common GADAG Root inside the local MRT Island, based on advertised priority values. The MRT Lowpoint algorithm simply requires that all routers in the MRT Island MUST select the same GADAG Root; the mechanism can vary based upon the MRT profile description. Before beginning computation, the network graph is reduced to contain only the set of routers that support the specific MRT profile whose MRTs are being computed.

[RFC7812]のセクション8.3では、デフォルトのMRTプロファイルのGADAGルート選択ポリシーが説明されています。この選択ポリシーにより、ルーターは、アドバタイズされた優先度の値に基づいて、ローカルMRTアイランド内の共通のGADAGルートを一貫して選択できます。 MRTローポイントアルゴリズムでは、MRTアイランドのすべてのルーターが同じGADAGルートを選択する必要があります。このメカニズムは、MRTプロファイルの説明に基づいて異なる場合があります。計算を開始する前に、ネットワークグラフが縮小され、MRTが計算されている特定のMRTプロファイルをサポートするルーターのセットのみが含まれます。

As noted in Section 7, pseudonodes MUST NOT be considered for GADAG root selection.

セクション7で述べたように、疑似ノードはGADAGルート選択で考慮してはなりません(MUST NOT)。

It is expected that an operator will designate a set of routers as good choices for selection as GADAG root by setting the GADAG Root Selection Priority for that set of routers to lower (more preferred) numerical values. For guidance on setting the GADAG Root Selection Priority values, refer to Section 9.1.

オペレーターは、ルーターのセットのGADAGルート選択優先度をより低い(より好ましい)数値に設定することにより、ルーターのセットをGADAGルートとして選択するための適切な選択肢として指定することが期待されます。 GADAG Root Selection Priority値の設定に関するガイダンスについては、セクション9.1を参照してください。

5.4. Initialization
5.4. 初期化

Before running the algorithm, there is the standard type of initialization to be done, such as clearing any computed DFS-values, lowpoint-values, DFS parents, lowpoint-parents, any MRT-computed next hops, and flags associated with algorithm.

アルゴリズムを実行する前に、計算されたDFS値、lowpoint-values、DFS親、lowpoint-parents、MRTで計算されたネクストホップ、アルゴリズムに関連付けられたフラグをクリアするなど、標準的なタイプの初期化が行われます。

It is assumed that a regular SPF computation has been run so that the primary next hops from the computing router to each destination are known. This is required for determining alternates at the last step.

コンピューティングルータから各宛先へのプライマリネクストホップがわかるように、定期的なSPF計算が実行されていると想定しています。これは、最後のステップで代替を決定するために必要です。

Initially, all interfaces MUST be initialized to UNDIRECTED. Whether they are OUTGOING, INCOMING, or both is determined when the GADAG is constructed and augmented.

最初は、すべてのインターフェースをUNDIRECTEDに初期化する必要があります。それらがOUTGOING、INCOMING、またはその両方であるかどうかは、GADAGが構築および拡張されるときに決定されます。

It is possible that some links and nodes will be marked using standard IGP mechanisms to discourage or prevent transit traffic. Section 7.3.1 of [RFC7812] describes how those links and nodes are excluded from MRT Island formation.

トランジットトラフィックを阻止または防止するために、一部のリンクおよびノー​​ドが標準のIGPメカニズムを使用してマークされる可能性があります。 [RFC7812]のセクション7.3.1は、これらのリンクとノードがMRTアイランドの形成から除外される方法を説明しています。

MRT-FRR also has the ability to advertise links MRT-Ineligible, as described in Section 7.3.2 of [RFC7812]. These links are excluded from the MRT Island and the GADAG. Computation of MRT next hops will therefore not use any MRT-ineligible links. The MRT Lowpoint algorithm does still need to consider MRT-ineligible links when computing FRR alternates, because an MRT-ineligible link can still be the shortest-path next hop to reach a destination.

[RFC7812]のセクション7.3.2で説明されているように、MRT-FRRはリンクをMRT非対象にアドバタイズすることもできます。これらのリンクは、MRTアイランドおよびGADAGから除外されています。したがって、MRTネクストホップの計算では、MRTに不適格なリンクは使用されません。 MRT不適格リンクは依然として宛先に到達するための最短パスネクストホップである可能性があるため、MRTローポイントアルゴリズムは、FRR代替を計算するときにMRT不適格リンクを考慮する必要があります。

When a broadcast interface is advertised as MRT-ineligible, then the pseudonode representing the entire broadcast network MUST NOT be included in the MRT Island. This is equivalent to excluding all of the broadcast interfaces on that broadcast network from the MRT Island.

ブロードキャストインターフェイスがMRT非対応としてアドバタイズされる場合、ブロードキャストネットワーク全体を表す疑似ノードをMRTアイランドに含めることはできません。これは、そのブロードキャストネットワーク上のすべてのブロードキャストインターフェイスをMRTアイランドから除外することと同じです。

5.5. Constructing the GADAG Using Lowpoint Inheritance
5.5. ローポイント継承を使用したGADAGの構築

As discussed in Section 4.2, it is necessary to find ears from a node x that is already in the GADAG (known as IN_GADAG). Two different methods are used to find ears in the algorithm. The first is by going to a DFS-child that is not IN_GADAG and then following the chain of lowpoint parents until an IN_GADAG node is found. The second is by going to a neighbor that is not IN_GADAG and then following the chain of DFS parents until an IN_GADAG node is found. As an ear is found, the associated interfaces are marked based on the direction taken. The nodes in the ear are marked as IN_GADAG. In the algorithm, first the ears via DFS-children are found and then the ears via DFS-neighbors are found.

セクション4.2で説明したように、すでにGADAGにあるノードx(IN_GADAGとして知られている)から耳を見つける必要があります。アルゴリズムで耳を見つけるには、2つの異なる方法が使用されます。 1つ目は、IN_GADAGではないDFS子に移動し、次にIN_GADAGノードが見つかるまでローポイント親のチェーンをたどることです。 2つ目は、IN_GADAGではないネイバーに移動し、IN_GADAGノードが見つかるまでDFS親のチェーンをたどることです。耳が見つかると、関連付けられたインターフェイスは、取られた方向に基づいてマークされます。耳のノードはIN_GADAGとしてマークされます。このアルゴリズムでは、最初にDFSチャイルドを介した耳が検出され、次にDFSネイバーを介した耳が検出されます。

By adding both types of ears when an IN_GADAG node is processed, all ears that connect to that node are found. The order in which the IN_GADAG nodes are processed is, of course, key to the algorithm. The order is a stack of ears so the most recent ear is found at the top of the stack. Of course, the stack stores nodes and not ears, so an ordered list of nodes, from the first node in the ear to the last node in the ear, is created as the ear is explored and then that list is pushed onto the stack.

IN_GADAGノードが処理されるときに両方のタイプの耳を追加することにより、そのノードに接続するすべての耳が見つかります。 IN_GADAGノードが処理される順序は、もちろん、アルゴリズムにとって重要です。順序は耳のスタックなので、最新の耳はスタックの一番上にあります。もちろん、スタックは耳ではなくノードを保存するため、耳の最初のノードから耳の最後のノードまでの順序付けられたノードのリストは、耳が探索されると作成され、そのリストがスタックにプッシュされます。

Each ear represents a partial order (see Figure 4) and processing the nodes in order along each ear ensures that all ears connecting to a node are found before a node higher in the partial order has its ears explored. This means that the direction of the links in the ear is always from the node x being processed towards the other end of the ear. Additionally, by using a stack of ears, this means that any unprocessed nodes in previous ears can only be ordered higher than nodes in the ears below it on the stack.

各耳は部分的な順序を表し(図4を参照)、各耳に沿ってノードを順番に処理することで、ノードに接続しているすべての耳が、部分的な順序で上位のノードが探索される前に確実に検出されます。これは、耳の中のリンクの方向が常に処理されているノードxから耳のもう一方の端に向かっていることを意味します。さらに、耳のスタックを使用することにより、前の耳の未処理ノードは、スタックの下にある耳のノードよりも高い順序でしか順序付けできないことを意味します。

In this algorithm that depends upon Lowpoint inheritance, it is necessary that every node has a lowpoint parent that is not itself. If a node is a cut-vertex, that may not yet be the case. Therefore, any nodes without a lowpoint parent will have their lowpoint parent set to their DFS parent and their lowpoint value set to the DFS-value of their parent. This assignment also properly allows an ear between two cut-vertices.

Lowpoint継承に依存するこのアルゴリズムでは、すべてのノードに、それ自体ではないLowpoint親が必要です。ノードがカット頂点である場合、まだそうではない可能性があります。したがって、下位ポイントの親がないノードでは、下位ポイントの親がDFS親に設定され、下位ポイントの値が親のDFS値に設定されます。この割り当てにより、2つのカット頂点間の耳も適切に許可されます。

Finally, the algorithm simultaneously computes each node's localroot, as described in Figure 12. This is further elaborated as follows. The localroot can be inherited from the node at the end of the ear unless the end of the ear is x itself, in which case the localroot for all the nodes in the ear would be x. This is because whenever the first cycle is found in a block, or an ear involving a bridge is computed, the cut-vertex closest to the root would be x itself. In all other scenarios, the properties of lowpoint/dfs parents ensure that the end of the ear will be in the same block, and thus inheriting its localroot would be the correct localroot for all newly added nodes.

最後に、図12で説明するように、アルゴリズムは各ノードのローカルルートを同時に計算します。これは、次のようにさらに詳しく説明されます。耳の端がx自体でない限り、ローカルルートは耳の端のノードから継承できます。その場合、耳のすべてのノードのローカルルートはxになります。これは、ブロックで最初のサイクルが見つかった場合、またはブリッジを含む耳が計算された場合は常に、ルートに最も近いカット頂点がx自体になるためです。他のすべてのシナリオでは、lowpoint / dfs親のプロパティにより、耳の端が同じブロック内にあることが保証されるため、そのローカルルートを継承すると、新しく追加されたすべてのノードの正しいローカルルートになります。

The pseudocode for the GADAG algorithm (assuming that the adjustment of lowpoint for cut-vertices has been made) is shown in Figure 17.

GADAGアルゴリズムの擬似コード(カット頂点の低点の調整が行われたと想定)を図17に示します。

Construct_Ear(x, Stack, intf, ear_type) ear_list = empty cur_node = intf.remote_node cur_intf = intf not_done = true

Construct_Ear(x、Stack、intf、ear_type)ear_list = empty cur_node = intf.remote_node cur_intf = intf not_done = true

while not_done cur_intf.UNDIRECTED = false cur_intf.OUTGOING = true cur_intf.remote_intf.UNDIRECTED = false cur_intf.remote_intf.INCOMING = true

一方not_done cur_intf.UNDIRECTED = false cur_intf.OUTGOING = true cur_intf.remote_intf.UNDIRECTED = false cur_intf.remote_intf.INCOMING = true

if cur_node.IN_GADAG is false cur_node.IN_GADAG = true add_to_list_end(ear_list, cur_node) if ear_type is CHILD cur_intf = cur_node.lowpoint_parent_intf cur_node = cur_node.lowpoint_parent else // ear_type must be NEIGHBOR cur_intf = cur_node.dfs_parent_intf cur_node = cur_node.dfs_parent else not_done = false

cur_node.IN_GADAGがfalseの場合cur_node.IN_GADAG = true add_to_list_end(ear_list、cur_node)ear_typeがCHILDの場合cur_intf = cur_node.lowpoint_parent_intf cur_node = cur_node.lowpoint_parent else // ear_typeはNEIGHBOR cur_intf_ cur_intf_ cur_node.curdnodeでなければなりません= false

              if (ear_type is CHILD) and (cur_node is x)
                 // x is a cut-vertex and the local root for
                 // the block in which the ear is computed
                 x.IS_CUT_VERTEX = true
                 localroot = x
              else
                 // Inherit localroot from the end of the ear
                 localroot = cur_node.localroot
              while ear_list is not empty
                 y = remove_end_item_from_list(ear_list)
                 y.localroot = localroot
                 push(Stack, y)
        

Construct_GADAG_via_Lowpoint(topology, gadag_root) gadag_root.IN_GADAG = true gadag_root.localroot = None Initialize Stack to empty push gadag_root onto Stack while (Stack is not empty) x = pop(Stack) foreach ordered_interface intf of x if ((intf.remote_node.IN_GADAG == false) and (intf.remote_node.dfs_parent is x)) Construct_Ear(x, Stack, intf, CHILD) foreach ordered_interface intf of x if ((intf.remote_node.IN_GADAG == false) and (intf.remote_node.dfs_parent is not x)) Construct_Ear(x, Stack, intf, NEIGHBOR)

Construct_GADAG_via_Lowpoint(topology、gadag_root)gadag_root.IN_GADAG = true gadag_root.localroot = None Stack to empty push gadag_root while(Stack is not empty)x = pop(Stack)foreach ordered_interface intf of x if((intf.remote_node.IN_GADAG == false)および(intf.remote_node.dfs_parent is x))Construct_Ear(x、Stack、intf、CHILD)foreach ordered_interface intf of x if((intf.remote_node.IN_GADAG == false)and(intf.remote_node.dfs_parent is not x))Construct_Ear(x、Stack、intf、NEIGHBOR)

Construct_GADAG_via_Lowpoint(topology, gadag_root)

Construct_GADAG_via_Lowpoint(トポロジ、gadag_root)

Figure 17: Lowpoint Inheritance GADAG Algorithm

図17:低点継承GADAGアルゴリズム

5.6. すべてのリンクを指示してGADAGを拡張する

The GADAG, regardless of the method used to construct it, at this point could be used to find MRTs, but the topology does not include all links in the network graph. That has two impacts. First, there might be shorter paths that respect the GADAG partial ordering and so the alternate paths would not be as short as possible. Second, there may be additional paths between a router x and the root that are not included in the GADAG. Including those provides potentially more bandwidth to traffic flowing on the alternates and may reduce congestion compared to just using the GADAG as currently constructed.

GADAGは、それを構築するために使用された方法に関係なく、この時点でMRTを見つけるために使用できますが、トポロジにはネットワークグラフ内のすべてのリンクが含まれていません。これには2つの影響があります。最初に、GADAGの部分的な順序を尊重する短いパスが存在する可能性があるため、代替パスは可能な限り短くなりません。次に、ルーターxとルートの間にGADAGに含まれていない追加のパスがある可能性があります。これらを含めると、代替で流れるトラフィックにより多くの帯域幅が提供される可能性があり、現在構築されているGADAGを単に使用する場合と比較して、輻輳を軽減できる可能性があります。

The goal is thus to assign direction to every remaining link marked as UNDIRECTED to improve the paths and number of paths found when the MRTs are computed.

したがって、目標は、MRTの計算時に検出されるパスとパスの数を改善するために、UNDIRECTEDとマークされた残りのすべてのリンクに方向を割り当てることです。

To do this, we need to establish a total order that respects the partial order described by the GADAG. This can be done using Kahn's topological sort [Kahn_1962_topo_sort], which essentially assigns a number to a node x only after all nodes before it (e.g., with a link incoming to x) have had their numbers assigned. The only issue with the topological sort is that it works on DAGs and not ADAGs or GADAGs.

これを行うには、GADAGによって記述された部分的な順序を尊重する合計順序を確立する必要があります。これは、カーンのトポロジカルソート[Kahn_1962_topo_sort]を使用して実行できます。これは、基本的に、ノードxに番号を割り当てるのは、その前にあるすべてのノード(たとえば、xに着信するリンク)に番号が割り当てられた後です。トポロジカルソートの唯一の問題は、ADAGまたはGADAGではなくDAGで機能することです。

To convert a GADAG to a DAG, it is necessary to remove all links that point to a root of block from within that block. That provides the necessary conversion to a DAG and then a topological sort can be done. When adding undirected links to the GADAG, links connecting the block root to other nodes in that block need special handling because the topological order will not always give the right answer for those links. There are three cases to consider. If the undirected link in question has another parallel link between the same two nodes that is already directed, then the direction of the undirected link can be inherited from the previously directed link. In the case of parallel cut links, we set all of the parallel links to both INCOMING and OUTGOING. Otherwise, the undirected link in question is set to OUTGOING from the block root node. A cut-link can then be identified by the fact that it will be directed both INCOMING and OUTGOING in the GADAG. The exact details of this whole process are captured in Figure 18.

GADAGをDAGに変換するには、そのブロック内からブロックのルートを指すすべてのリンクを削除する必要があります。これにより、必要なDAGへの変換が提供され、トポロジーソートを実行できます。 GADAGに無向リンクを追加する場合、ブロックルートをそのブロック内の他のノードに接続するリンクは、トポロジーの順序がこれらのリンクに常に正しい答えを与えるとは限らないため、特別な処理が必要です。考慮すべき3つのケースがあります。問題の無向リンクに、すでに誘導されている同じ2つのノード間に別の並列リンクがある場合、無向リンクの方向は、以前に誘導されたリンクから継承できます。平行カットリンクの場合、すべての平行リンクをINCOMINGとOUTGOINGの両方に設定します。それ以外の場合、問題の無向リンクは、ブロックルートノードからOUTGOINGに設定されます。カットリンクは、それがGADAGで着信と発信の両方に向けられるという事実によって識別できます。このプロセス全体の詳細を図18に示します。

Add_Undirected_Block_Root_Links(topo, gadag_root) foreach node x in topo if x.IS_CUT_VERTEX or x is gadag_root foreach interface i of x if (i.remote_node.localroot is not x or i.PROCESSED ) continue Initialize bundle_list to empty bundle.UNDIRECTED = true bundle.OUTGOING = false bundle.INCOMING = false foreach interface i2 in x if i2.remote_node is i.remote_node add_to_list_end(bundle_list, i2) if not i2.UNDIRECTED: bundle.UNDIRECTED = false if i2.INCOMING: bundle.INCOMING = true if i2.OUTGOING: bundle.OUTGOING = true if bundle.UNDIRECTED foreach interface i3 in bundle_list i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.OUTGOING = true i3.remote_intf.INCOMING = true else if (bundle.OUTGOING and bundle.INCOMING) foreach interface i3 in bundle_list i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.OUTGOING = true i3.INCOMING = true i3.remote_intf.INCOMING = true i3.remote_intf.OUTGOING = true

Add_Undirected_Block_Root_Links(topo、gadag_root)foreach node x in topo if x.IS_CUT_VERTEX or x is gadag_root foreach interface i of x if(i.remote_node.localroot is not x or i.PROCESSED)continue bundle_list to empty bundle.UNDIRECTED = true bundle .OUTGOING = false bundle.INCOMING = false i2.remote_nodeがi.remote_nodeの場合、x内のi2のforiインターフェースadd_to_list_end(bundle_list、i2)if not i2.UNDIRECTED:bundle.UNDIRECTED = false if i2.INCOMING:bundle.INCOMING = true if i2.OUTGOING:bundle.OUTGOING = true if bundle.UNDIRECTED foreach interface i3 in bundle_list i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.OUTGOING = true i3.remote_intf .INCOMING = true else if(bundle.OUTGOINGおよびbundle.INCOMING)foreachインターフェースi3 bundle_list i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.OUTGOING = true i3 .INCOMING = true i3.remote_intf.INCOMING = true i3 .remote_intf.OUTGOING = true

else if bundle.OUTGOING foreach interface i3 in bundle_list i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.OUTGOING = true i3.remote_intf.INCOMING = true else if bundle.INCOMING foreach interface i3 in bundle_list i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.INCOMING = true i3.remote_intf.OUTGOING = true

else if bundle.OUTGOING foreachインターフェースi3 bundle_list内i3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.OUTGOING = true i3.remote_intf.INCOMING = trueバンドルされている場合はそれ以外。 bundle_list内の着信foreachインターフェースi3.UNDIRECTED = false i3.remote_intf.UNDIRECTED = false i3.PROCESSED = true i3.remote_intf.PROCESSED = true i3.INCOMING = true i3.remote_intf.OUTGOING = true

Modify_Block_Root_Incoming_Links(topo, gadag_root) foreach node x in topo if x.IS_CUT_VERTEX or x is gadag_root foreach interface i of x if i.remote_node.localroot is x if i.INCOMING: i.INCOMING = false i.INCOMING_STORED = true i.remote_intf.OUTGOING = false i.remote_intf.OUTGOING_STORED = true

Modify_Block_Root_Incoming_Links(topo、gadag_root)foreach node x in topo if x.IS_CUT_VERTEX or x is gadag_root foreach interface i of x if i.remote_node.localroot is x if i.INCOMING:i.INCOMING = false i.INCOMING_STORED = true i.remote_int .OUTGOING = false i.remote_intf.OUTGOING_STORED = true

Revert_Block_Root_Incoming_Links(topo, gadag_root) foreach node x in topo if x.IS_CUT_VERTEX or x is gadag_root foreach interface i of x if i.remote_node.localroot is x if i.INCOMING_STORED i.INCOMING = true i.remote_intf.OUTGOING = true i.INCOMING_STORED = false i.remote_intf.OUTGOING_STORED = false

Revert_Block_Root_Incoming_Links(topo、gadag_root)foreach node x in topo if x.IS_CUT_VERTEX or x is gadag_root foreach interface i of x if i.remote_node.localroot is x if i.INCOMING_STORED i.INCOMING = true i.remote_intf.OUTGOING = true INCOMING_STORED = false i.remote_intf.OUTGOING_STORED = false

Run_Topological_Sort_GADAG(topo, gadag_root) Modify_Block_Root_Incoming_Links(topo, gadag_root) foreach node x in topo node.unvisited = 0 foreach interface i of x if (i.INCOMING) node.unvisited += 1 Initialize working_list to empty Initialize topo_order_list to empty add_to_list_end(working_list, gadag_root) while working_list is not empty y = remove_start_item_from_list(working_list) add_to_list_end(topo_order_list, y) foreach ordered_interface i of y if intf.OUTGOING i.remote_node.unvisited -= 1 if i.remote_node.unvisited is 0 add_to_list_end(working_list, i.remote_node) next_topo_order = 1 while topo_order_list is not empty y = remove_start_item_from_list(topo_order_list) y.topo_order = next_topo_order next_topo_order += 1 Revert_Block_Root_Incoming_Links(topo, gadag_root)

xのトポnode.unvisited = 0 foreachの界面におけるRun_Topological_Sort_GADAG(TOPO、gadag_root)Modify_Block_Root_Incoming_Links(TOPO、gadag_root)foreachのノードX iが(i.INCOMING)node.unvisited + = 1初期working_list空add_to_list_end(working_listに初期化topo_order_listを空にした場合、gadag_root)working_listが空でない場合y = remove_start_item_from_list(working_list)add_to_list_end(topo_order_list、y)foreach ordered_interface i of y if intf.OUTGOING i.remote_node.unvisited-= 1 if i.remote_node.unvisitlist is 0 add_to_work_list .remote_node)next_topo_order = 1 while topo_order_list is empty not y = remove_start_item_from_list(topo_order_list)y.topo_order = next_topo_order next_topo_order + = 1 Revert_Block_Root_Incoming_Links(topo、gadag_root)

def Set_Other_Undirected_Links_Based_On_Topo_Order(topo) foreach node x in topo foreach interface i of x if i.UNDIRECTED: if x.topo_order < i.remote_node.topo_order i.OUTGOING = true i.UNDIRECTED = false i.remote_intf.INCOMING = true i.remote_intf.UNDIRECTED = false else i.INCOMING = true i.UNDIRECTED = false i.remote_intf.OUTGOING = true i.remote_intf.UNDIRECTED = false

def Set_Other_Undirected_Links_Based_On_Topo_Order(topo)foreach node x in topo foreach interface i of x if i.UNDIRECTED:if x.topo_order <i.remote_node.topo_order i.OUTGOING = true i.UNDIRECTED = false i.remote_intf.INCOMING = true i.remote_f .UNDIRECTED = false else i.INCOMING = true i.UNDIRECTED = false i.remote_intf.OUTGOING = true i.remote_intf.UNDIRECTED = false

Add_Undirected_Links(topo, gadag_root) Add_Undirected_Block_Root_Links(topo, gadag_root) Run_Topological_Sort_GADAG(topo, gadag_root) Set_Other_Undirected_Links_Based_On_Topo_Order(topo)

Add_Undirected_Links(topo、gadag_root)Add_Undirected_Block_Root_Links(topo、gadag_root)Run_Topological_Sort_GADAG(topo、gadag_root)Set_Other_Undirected_Links_Based_On_Topo_Order(topo)

Add_Undirected_Links(topo, gadag_root)

Add_undirected_links(hat、gadag_root)

Figure 18: Assigning Direction to UNDIRECTED Links

図18:UNDIRECTEDリンクへの方向の割り当て

Proxy-nodes do not need to be added to the network graph. They cannot be transited and do not affect the MRTs that are computed. The details of how the MRT-Blue and MRT-Red next hops are computed for proxy-nodes and how the appropriate alternate next hops are selected is given in Section 5.9.

プロキシノードをネットワークグラフに追加する必要はありません。それらは通過できず、計算されるMRTに影響を与えません。プロキシノードのMRT-BlueおよびMRT-Redネクストホップの計算方法と、適切な代替ネクストホップの選択方法の詳細については、セクション5.9を参照してください。

5.7. Compute MRT Next Hops
5.7. MRTネクストホップの計算

As was discussed in Section 4.1, once an ADAG is found, it is straightforward to find the next hops from any node X to the ADAG root. However, in this algorithm, we will reuse the common GADAG and find not only the one pair of MRTs rooted at the GADAG root with it, but find a pair rooted at each node. This is useful since it is significantly faster to compute.

セクション4.1で説明したように、ADAGが見つかったら、任意のノードXからADAGルートへの次のホップを見つけるのは簡単です。ただし、このアルゴリズムでは、共通のGADAGを再利用して、GADAGルートをルートとする1組のMRTだけでなく、各ノードをルートとするペアも見つけます。計算が大幅に高速になるため、これは便利です。

The method for computing differently rooted MRTs from the common GADAG is based on two ideas. First, if two nodes X and Y are ordered with respect to each other in the partial order, then an SPF along OUTGOING links (an increasing-SPF) and an SPF along INCOMING links (a decreasing-SPF) can be used to find the increasing and decreasing paths. Second, if two nodes X and Y aren't ordered with respect to each other in the partial order, then intermediary nodes can be used to create the paths by increasing/decreasing to the intermediary and then decreasing/increasing to reach Y.

一般的なGADAGとは異なるルートのMRTを計算する方法は、2つのアイデアに基づいています。まず、2つのノードXとYが相互に部分的な順序で並べられている場合、OUTGOINGリンクに沿ったSPF(増加するSPF)とINCOMINGリンクに沿ったSPF(減少するSPF)を使用して、パスの増減。 2番目に、2つのノードXとYが部分的な順序で互いに対して順序付けられていない場合、中間ノードを使用して、中間ノードに増加/減少し、次に減少/増加してYに到達することにより、パスを作成できます。

As usual, the two basic ideas will be discussed assuming the network is 2-connected. The generalization to multiple blocks is discussed in Section 5.7.4. The full algorithm is given in Section 5.7.5.

いつものように、ネットワークが2つ接続されていると仮定して、2つの基本的なアイデアについて説明します。複数のブロックへの一般化については、セクション5.7.4で説明します。完全なアルゴリズムはセクション5.7.5に記載されています。

5.7.1. MRT Next Hops to All Nodes Ordered with Respect to the Computing Node

5.7.1. コンピューティングノードに関して順序付けられたすべてのノードへのMRTネクストホップ

Finding two node-disjoint paths from the computing router X to any node Y depends upon whether Y>>X or Y<<X. As shown in Figure 19, if Y>>X, then there is an increasing path that goes from X to Y without crossing R; this contains nodes in the interval [X,Y]. There is also a decreasing path that decreases towards R and then decreases from R to Y; this contains nodes in the interval [X,R-small] or [R-great,Y]. The two paths cannot have common nodes other than X and Y.

コンピューティングルータXから任意のノードYへの2つのノード分離パスを見つけることは、Y >> XかY << Xかによって異なります。図19に示すように、Y >> Xの場合、Rを横切ることなくXからYに向かう増加するパスがあります。これには、間隔[X、Y]のノードが含まれます。 Rに向かって減少し、次にRからYに減少する減少経路もあります。これには、間隔[X、R-small]または[R-great、Y]のノードが含まれます。 2つのパスにXとY以外の共通ノードを含めることはできません。

                     [Y]<---(Cloud 2)<--- [X]
                      |                    ^
                      |                    |
                      V                    |
                   (Cloud 3)--->[R]--->(Cloud 1)
        
                  MRT-Blue path: X->Cloud 2->Y
                  MRT-Red path: X->Cloud 1->R->Cloud 3->Y
        
                              Figure 19: Y>>X
        

Similar logic applies if Y<<X, as shown in Figure 20. In this case, the increasing path from X increases to R and then increases from R to Y to use nodes in the intervals [X,R-great] and [R-small, Y]. The decreasing path from X reaches Y without crossing R and uses nodes in the interval [Y,X].

図20に示すように、Y << Xの場合も同様のロジックが適用されます。この場合、XからRに増加するパスが増加し、次にRからYに増加して、[X、R-great]と[R -小、Y]。 Xからの減少経路は、Rを横切ることなくYに到達し、区間[Y、X]のノードを使用します。

                    [X]<---(Cloud 2)<--- [Y]
                     |                    ^
                     |                    |
                     V                    |
                  (Cloud 3)--->[R]--->(Cloud 1)
        
                 MRT-Blue path: X->Cloud 3->R->Cloud 1->Y
                 MRT-Red path: X->Cloud 2->Y
        
                              Figure 20: Y<<X
        

5.7.2. MRT Next Hops to All Nodes Not Ordered with Respect to the Computing Node

5.7.2. コンピューティングノードに関して順序付けられていないすべてのノードへのMRTネクストホップ

When X and Y are not ordered, the first path should increase until we get to a node G, where G>>Y. At G, we need to decrease to Y. The other path should be just the opposite: we must decrease until we get to a node H, where H<<Y, and then increase. Since R is smaller and greater than Y, such G and H must exist. It is also easy to see that these two paths must be node disjoint: the first path contains nodes in interval [X,G] and [Y,G], while the second path contains nodes in interval [H,X] and [H,Y]. This is illustrated in Figure 21. It is necessary to decrease and then increase for the MRT-Blue and increase and then decrease for the MRT-Red; if one simply increased for one and decreased for the other, then both paths would go through the root R.

XとYが順序付けられていない場合、最初のパスはノードGに到達するまで増加するはずです。ここでG >> Yです。 Gで、Yに減少する必要があります。他のパスは正反対でなければなりません。ノードHに到達するまで減少しなければなりません。ここで、H << Yで、その後増加します。 RはYより小さくて大きいので、そのようなGとHが存在する必要があります。これらの2つのパスはノードの素である必要があることも簡単にわかります。最初のパスには間隔[X、G]と[Y、G]のノードが含まれ、2番目のパスには間隔[H、X]と[H 、Y]。これを図21に示します。MRT-Blueの場合は減少してから増加し、MRT-Redの場合は増加してから減少する必要があります。一方が単に増加し、他方が減少した場合、両方のパスがルートRを通過します。

                 (Cloud 6)<---[Y]<---(Cloud 5)<------------|
                   |                                       |
                   |                                       |
                   V                                       |
                  [G]--->(Cloud 4)--->[R]--->(Cloud 1)--->[H]
                   ^                                       |
                   |                                       |
                   |                                       |
                  (Cloud 3)<---[X]<---(Cloud 2)<-----------|
        
              MRT-Blue path: decrease to H and increase to Y
                   X->Cloud 2->H->Cloud 5->Y
              MRT-Red path:  increase to G and decrease to Y
                   X->Cloud 3->G->Cloud 6->Y
        

Figure 21: X and Y Unordered

図21:XとYの順序付けなし

This gives disjoint paths as long as G and H are not the same node. Since G>>Y and H<<Y, if G and H could be the same node, that would have to be the root R. This is not possible because there is only one incoming interface to the root R that is created when the initial cycle is found. Recall from Figure 6 that whenever an ear was found to have an end that was the root R, the ear was directed from R so that the associated interface on R is outgoing and not incoming. Therefore, there must be exactly one node M that is the largest one before R, so the MRT-Red path will never reach R; it will turn at M and decrease to Y.

これにより、GとHが同じノードでない限り、パスがばらばらになります。 G >> YとH << Yなので、GとHが同じノードである場合、それはルートRである必要があります。ルートRへの着信インターフェイスが1つしかないため、これは不可能です。初期サイクルが見つかりました。図6を思い出してください。耳がルートRである端があることがわかったときはいつでも、耳はRから誘導されたため、Rの関連するインターフェースは発信であり着信ではありません。したがって、Rの前に最大のノードMが1つだけ存在する必要があるため、MRT-RedパスはRに到達しません。 Mで曲がり、Yに減少します。

5.7.3. Computing Redundant Tree Next Hops in a 2-Connected Graph
5.7.3. 2連結グラフでの冗長ツリーのネクストホップの計算

The basic ideas for computing RT next hops in a 2-connected graph were given in Sections 5.7.1 and 5.7.2. Given these two ideas, how can we find the trees?

2連結グラフでRTネクストホップを計算するための基本的なアイデアは、セクション5.7.1および5.7.2に記載されています。これらの2つの考えを踏まえて、どのようにして木を見つけることができますか

If some node X only wants to find the next hops (which is usually the case for IP networks), it is enough to find which nodes are greater and less than X, and which are not ordered; this can be done by running an increasing-SPF and a decreasing-SPF rooted at X and not exploring any links from the ADAG root.

一部のノードXがネクストホップのみを検索したい場合(通常はIPネットワークの場合です)、Xより大きいノードとXより小さいノード、および順序付けされていないノードを見つけるだけで十分です。これは、Xをルートとし、ADAGルートからのリンクを探索せずに、増加するSPFおよび減少するSPFを実行することで実行できます。

In principle, a traversal method other than SPF could be used to traverse the GADAG in the process of determining blue and red next hops that result in maximally redundant trees. This will be the case as long as one traversal uses the links in the direction specified by the GADAG and the other traversal uses the links in the direction opposite of that specified by the GADAG. However, a different traversal algorithm will generally result in different blue and red next hops. Therefore, the algorithm specified here requires the use of SPF to traverse the GADAG to generate MRT blue and red next hops, as described below.

原則として、SPF以外のトラバーサル方法を使用して、最大冗長ツリーをもたらす青と赤のネクストホップを決定するプロセスでGADAGをトラバースできます。これは、1つのトラバーサルがGADAGによって指定された方向のリンクを使用し、他のトラバーサルがGADAGによって指定された方向と反対の方向のリンクを使用する限り当てはまります。ただし、トラバーサルアルゴリズムが異なると、通常、青と赤のネクストホップも異なります。したがって、ここで指定するアルゴリズムでは、SPFを使用してGADAGをトラバースし、MRTの青と赤のネクストホップを生成する必要があります。

An increasing-SPF rooted at X and not exploring links from the root will find the increasing next hops to all Y>>X. Those increasing next hops are X's next hops on the MRT-Blue to reach Y. A decreasing-SPF rooted at X and not exploring links from the root will find the decreasing next hops to all Z<<X. Those decreasing next hops are X's next hops on the MRT-Red to reach Z. Since the root R is both greater than and less than X, after this increasing-SPF and decreasing-SPF, X's next hops on the MRT-Blue and on the MRT-Red to reach R are known. For every node Y>>X, X's next hops on the MRT-Red to reach Y are set to those on the MRT-Red to reach R. For every node Z<<X, X's next hops on the MRT-Blue to reach Z are set to those on the MRT-Blue to reach R.

Xをルートとし、ルートからのリンクを探索しない増加するSPFは、すべてのY >> Xへの増加するネクストホップを見つけます。これらの増加するネクストホップは、Yに到達するためのMRTブルーのXのネクストホップです。Xをルートとし、ルートからのリンクを探索しない減少するSPFは、すべてのZ << Xへのネクストホップの減少を検出します。これらの減少するネクストホップは、Zに到達するためのMRT-Red上のXのネクストホップです。ルートRはどちらもXよりも大きいか小さいので、この増加するSPFと減少するSPFの後、MRT-Blue上のXの次のホップRに到達するMRT-Redは既知です。すべてのノードY >> Xについて、Yに到達するためのMRT-Red上のXの次のホップは、Rに到達するためのMRT-Red上のそれらに設定されます。すべてのノードZ << Xについて、到達するMRT-Blue上のXの次のホップZは、MRTブルーのRに到達するように設定されています。

For those nodes that were not reached by either the increasing-SPF or the decreasing-SPF, we can determine the next hops as well. The increasing MRT-Blue next hop for a node that is not ordered with respect to X is the next hop along the decreasing MRT-Red towards R, and the decreasing MRT-Red next hop is the next hop along the increasing MRT-Blue towards R. Naturally, since R is ordered with respect to all the nodes, there will always be an increasing and a decreasing path towards it. This algorithm does not provide the complete specific path taken but just the appropriate next hops to use. The identities of G and H are not determined by the computing node X.

増加するSPFまたは減少するSPFのいずれでも到達しなかったノードについては、ネクストホップも決定できます。 Xに関して順序付けられていないノードの増加するMRT-Blueネクストホップは、Rに向かう減少するMRT-Redに沿ったネクストホップであり、減少するMRT-Redネクストホップは、増加するMRT-Blueに向かうネクストホップです。 R.当然、Rはすべてのノードに対して順序付けられているため、Rへの経路は常に増加し、減少します。このアルゴリズムは、特定の完全なパスを提供するのではなく、使用する適切なネクストホップを提供します。 GとHのIDは、計算ノードXによって決定されません。

The final case to consider is when the GADAG root R computes its own next hops. Since the GADAG root R is << all other nodes, running an increasing-SPF rooted at R will reach all other nodes; the MRT-Blue next hops are those found with this increasing-SPF. Similarly, since the GADAG root R is >> all other nodes, running a decreasing-SPF rooted at R will reach all other nodes; the MRT-Red next hops are those found with this decreasing-SPF.

考慮すべき最後のケースは、GADAGルートRが独自のネクストホップを計算する場合です。 GADAGルートRは<<他のすべてのノードなので、Rをルートとする増加するSPFを実行すると、他のすべてのノードに到達します。 MRTブルーのネクストホップは、この増加するSPFで見つかったホップです。同様に、GADAGルートRは他のすべてのノード>>であるため、Rをルートとする減少するSPFを実行すると、他のすべてのノードに到達します。 MRTレッドのネクストホップは、この減少するSPFで見つかったホップです。

                 E---D---|              E<--D<--|
                 |   |   |              |   ^   |
                 |   |   |              V   |   |
                 R   F   C              R   F   C
                 |   |   |              |   ^   ^
                 |   |   |              V   |   |
                 A---B---|              A-->B---|
        

(a) (b) A 2-connected graph A spanning ADAG rooted at R

(a)(b)2連結グラフAをルートとするADAGにまたがるグラフ

Figure 22

図22

As an example, consider the situation depicted in Figure 22. Node C runs an increasing-SPF and a decreasing-SPF on the ADAG. The increasing-SPF reaches D, E, and R; the decreasing-SPF reaches B, A, and R. E>>C. So, towards E the MRT-Blue next hop is D, since E was reached on the increasing path through D. The MRT-Red next hop towards E is B, since R was reached on the decreasing path through B. Since E>>D, D will similarly compute its MRT-Blue next hop to be E, ensuring that a packet on MRT-Blue will use path C-D-E. B, A, and R will similarly compute the MRT-Red next hops towards E (which is ordered less than B, A and R), ensuring that a packet on MRT-Red will use path C-B-A-R-E.

例として、図22に示す状況を考えます。ノードCは、ADAGで増加するSPFと減少するSPFを実行します。増加するSPFはD、E、およびRに到達します。減少するSPFはB、A、およびRに達します。E>> C。したがって、EへのMRT-BlueネクストホップはDです。これは、Dを介して増加するパスでEに到達したためです。RがBを介して減少するパスで到達したため、EへのMRT-RedネクストホップはBです。 D、Dも同様に、MRTブルーのネクストホップをEとして計算し、MRTブルーのパケットがパスCDEを使用するようにします。 B、A、およびRは同様に、EへのMRT-Redネクストホップ(B、A、およびRよりも少ない順序)を計算し、MRT-Red上のパケットがパスC-B-A-R-Eを使用するようにします。

C can determine the next hops towards F as well. Since F is not ordered with respect to C, the MRT-Blue next hop is the decreasing one towards R (which is B) and the MRT-Red next hop is the increasing one towards R (which is D). Since F>>B, for its MRT-Blue next hop towards F, B will use the real increasing next hop towards F. So a packet forwarded to B on MRT-Blue will get to F on path C-B-F. Similarly, D will use the real decreasing next hop towards F as its MRT-Red next hop, a packet on MRT-Red will use path C-D-F.

CはFへのネクストホップも決定できます。 FはCに関して順序付けられていないため、MRT-BlueネクストホップはR(B)に向かって減少し、MRT-RedネクストホップはR(D)に向かって増加します。 F >> Bなので、FへのMRT-Blueネクストホップでは、BはFへの実際の増加するネクストホップを使用します。したがって、MRT-BlueでBに転送されたパケットは、パスC-B-FでFに到達します。同様に、DはMRT-RedネクストホップとしてFへの実際の減少するネクストホップを使用し、MRT-Red上のパケットはパスC-D-Fを使用します。

5.7.4. Generalizing for a Graph That Isn't 2-Connected
5.7.4. 2連結でないグラフの一般化

If a graph isn't 2-connected, then the basic approach given in Section 5.7.3 needs some extensions to determine the appropriate MRT next hops to use for destinations outside the computing router X's blocks. In order to find a pair of maximally redundant trees in that graph, we need to find a pair of RTs in each of the blocks (the root of these trees will be discussed later) and combine them.

グラフが2連結でない場合、セクション5.7.3に示す基本的なアプローチでは、コンピューティングルータXのブロック外の宛先に使用する適切なMRTネクストホップを決定するために、いくつかの拡張が必要です。そのグラフで最大冗長ツリーのペアを見つけるには、各ブロックでRTのペアを見つけ(これらのツリーのルートについては後で説明します)、それらを結合する必要があります。

When computing the MRT next hops from a router X, there are three basic differences:

ルータXからMRTネクストホップを計算する場合、3つの基本的な違いがあります。

1. Only nodes in a common block with X should be explored in the increasing-SPF and decreasing-SPF.

1. Xを含む共通ブロック内のノードのみを、増加するSPFおよび減少するSPFで探索する必要があります。

2. Instead of using the GADAG root, X's localroot should be used. This has the following implications:

2. GADAGルートを使用する代わりに、Xのローカルルートを使用する必要があります。これには次の影響があります。

A. The links from X's localroot should not be explored.

A. Xのローカルルートからのリンクは調査しないでください。

B. If a node is explored in the outgoing SPF so Y>>X, then X's MRT-Red next hops to reach Y uses X's MRT-Red next hops to reach X's localroot and if Z<<X, then X's MRT-Blue next hops to reach Z uses X's MRT-Blue next hops to reach X's localroot.

B.ノードが発信SPFで探索され、Y >> Xの場合、Yに到達するためのXのMRT-Redネクストホップは、XのMRT-Redネクストホップを使用してXのローカルルートに到達し、Z << Xの場合、XのMRT-Blue Zに到達するための次のホップは、Xのローカルルートに到達するためにXのMRT-Blueの次のホップを使用します。

C. If a node W in a common block with X was not reached in the increasing-SPF or decreasing-SPF, then W is unordered with respect to X. X's MRT-Blue next hops to W are X's decreasing (aka MRT-Red) next hops to X's localroot. X's MRT-Red next hops to W are X's increasing (aka MRT-Blue) next hops to X's localroot.

C. Xとの共通ブロック内のノードWが増加するSPFまたは減少するSPFで到達しなかった場合、WはXに関して順序付けされていません。 )Xのローカルルートへの次のホップ。 XのWへのMRT-Redネクストホップは、XのローカルルートへのXの増加(別名MRT-Blue)ネクストホップです。

3. For nodes in different blocks, the next hops must be inherited via the relevant cut-vertex.

3. 異なるブロックのノードの場合、ネクストホップは関連するカット頂点を介して継承する必要があります。

These are all captured in the detailed algorithm given in Section 5.7.5.

これらはすべて、セクション5.7.5に示す詳細なアルゴリズムで取得されます。

5.7.5. Complete Algorithm to Compute MRT Next Hops
5.7.5. MRTネクストホップを計算するための完全なアルゴリズム

The complete algorithm to compute MRT Next Hops for a particular router X is given in Figure 23. In addition to computing the MRT-Blue next hops and MRT-Red next hops used by X to reach each node Y, the algorithm also stores an "order_proxy", which is the proper cut-vertex to reach Y if it is outside the block, and which is used later in deciding whether the MRT-Blue or the MRT-Red can provide an acceptable alternate for a particular primary next hop.

特定のルーターXのMRTネクストホップを計算するための完全なアルゴリズムを図23に示します。Xが各ノードYに到達するために使用するMRT-BlueネクストホップとMRT-Redネクストホップの計算に加えて、アルゴリズムは「 order_proxy "。これは、ブロックの外側にある場合にYに到達するための適切なカット頂点であり、MRT-BlueまたはMRT-Redが特定のプライマリネクストホップに受け入れ可能な代替を提供できるかどうかを後で決定するときに使用されます。

In_Common_Block(x, y) if ( (x.block_id is y.block_id) or (x is y.localroot) or (y is x.localroot) ) return true return false

In_Common_Block(x、y)if((x.block_id is y.block_id)or(x is y.localroot)or(y is x.localroot))return true return false

Store_Results(y, direction) if direction is FORWARD y.higher = true y.blue_next_hops = y.next_hops if direction is REVERSE y.lower = true y.red_next_hops = y.next_hops

Store_Results(y、direction)方向がFORWARDの場合y.higher = true y.blue_next_hops = y.next_hops方向がREVERSEの場合y.lower = true y.red_next_hops = y.next_hops

SPF_No_Traverse_Block_Root(spf_root, block_root, direction) Initialize spf_heap to empty Initialize nodes' spf_metric to infinity and next_hops to empty spf_root.spf_metric = 0 insert(spf_heap, spf_root) while (spf_heap is not empty) min_node = remove_lowest(spf_heap) Store_Results(min_node, direction) if ((min_node is spf_root) or (min_node is not block_root)) foreach interface intf of min_node if ( ( ((direction is FORWARD) and intf.OUTGOING) or ((direction is REVERSE) and intf.INCOMING) ) and In_Common_Block(spf_root, intf.remote_node) ) path_metric = min_node.spf_metric + intf.metric if path_metric < intf.remote_node.spf_metric intf.remote_node.spf_metric = path_metric if min_node is spf_root intf.remote_node.next_hops = make_list(intf) else intf.remote_node.next_hops = min_node.next_hops insert_or_update(spf_heap, intf.remote_node) else if path_metric == intf.remote_node.spf_metric if min_node is spf_root add_to_list(intf.remote_node.next_hops, intf) else add_list_to_list(intf.remote_node.next_hops, min_node.next_hops)

SPF_No_Traverse_Block_Root(spf_root、block_root、direction)spf_heapを空に初期化してノードのspf_metricを無限大に初期化し、next_hopsを空のspf_rootに初期化します。spf_metric= 0 insert(spf_heap、spf_root)while(spf_heap is empty)min_node = remove_lowap(s) direction)if(((min_node is spf_root)または(min_node is not block_root))foreachインターフェイスintf of min_node if((((direction is FORWARD)and intf.OUTGOING)または((direction is REVERSE)and intf.INCOMING))およびIn_Common_Block(spf_root、intf.remote_node))path_metric = min_node.spf_metric + intf.metric if path_metric <intf.remote_node.spf_metric intf.remote_node.spf_metric = path_metric if min_node is spf_root intf.remhop_node.nextf_remhop_node.nextf_remhop_nextf_remhop_nextf_remote_node remote_node.next_hops = min_node.next_hops insert_or_update(spf_heap、intf.remote_node)else if path_metric == intf.remote_node.spf_metric if min_node is spf_root add_to_list(intf.remote_node.next_hops、intf.el_add_list ote_node.next_hops、min_node.next_hops)

SetEdge(y) if y.blue_next_hops is empty and y.red_next_hops is empty SetEdge(y.localroot) y.blue_next_hops = y.localroot.blue_next_hops y.red_next_hops = y.localroot.red_next_hops y.order_proxy = y.localroot.order_proxy

SetEdge(y)(y.blue_next_hopsが空でy.red_next_hopsが空の場合)SetEdge(y.localroot)y.blue_next_hops = y.localroot.blue_next_hops y.red_next_hops = y.localroot.red_next_hops y.order_proxy = y.localroot.order_proxy

Compute_MRT_NextHops(x, gadag_root) foreach node y y.higher = y.lower = false clear y.red_next_hops and y.blue_next_hops y.order_proxy = y SPF_No_Traverse_Block_Root(x, x.localroot, FORWARD) SPF_No_Traverse_Block_Root(x, x.localroot, REVERSE)

Compute_MRT_NextHops(x、gadag_root)foreachノードy y.higher = y.lower = falseクリアy.red_next_hopsおよびy.blue_next_hops y.order_proxy = y SPF_No_Traverse_Block_Root(x、x.localroot、FORWARD)SPF_No_Traverse_Block_Root(x) )

      // red and blue next hops are stored to x.localroot as different
      // paths are found via the SPF and reverse-SPF.
      // Similarly, any node whose localroot is x will have its
      // red_next_hops and blue_next_hops already set.
        

// Handle nodes in the same block that aren't the localroot foreach node y if (y.IN_MRT_ISLAND and (y is not x) and (y.block_id is x.block_id) ) if y.higher y.red_next_hops = x.localroot.red_next_hops else if y.lower y.blue_next_hops = x.localroot.blue_next_hops else y.blue_next_hops = x.localroot.red_next_hops y.red_next_hops = x.localroot.blue_next_hops

//(y.IN_MRT_ISLAND and(y is not x)and(y.block_id is x.block_id))if y.higher y.red_next_hops = xの場合、ローカルルートforeachノードyではない同じブロック内のノードを処理します。 localroot.red_next_hops else if y.lower y.blue_next_hops = x.localroot.blue_next_hops else y.blue_next_hops = x.localroot.red_next_hops y.red_next_hops = x.localroot.blue_next_hops

// Inherit next hops and order_proxies to other components if (x is not gadag_root) and (x.localroot is not gadag_root) gadag_root.blue_next_hops = x.localroot.blue_next_hops gadag_root.red_next_hops = x.localroot.red_next_hops gadag_root.order_proxy = x.localroot foreach node y if (y is not gadag_root) and (y is not x) and y.IN_MRT_ISLAND SetEdge(y)

//(xがgadag_rootでない)および(x.localrootがgadag_rootでない)場合は、ネクストホップとorder_proxiesを他のコンポーネントに継承します。 (yがgadag_rootではなく)、(yがxではない)およびyの場合、ローカルルートforeachノードy.IN_MRT_ISLAND SetEdge(y)

max_block_id = 0 Assign_Block_ID(gadag_root, max_block_id) Compute_MRT_NextHops(x, gadag_root)

max_block_id = 0 Assign_Block_ID(gadag_root、max_block_id)Compute_MRT_NextHops(x、gadag_root)

Figure 23: Complete Algorithm to Compute MRT Next Hops

図23:MRTネクストホップを計算する完全なアルゴリズム

5.8. Identify MRT Alternates
5.8. MRT代替の識別

At this point, a computing router S knows its MRT-Blue next hops and MRT-Red next hops for each destination in the MRT Island. The primary next hops along the SPT are also known. It remains to determine for each primary next hop to a destination D, which MRT avoids the primary next-hop node F. This computation depends upon data set in Compute_MRT_NextHops such as each node y's y.blue_next_hops, y.red_next_hops, y.order_proxy, y.higher, y.lower, and topo_orders. Recall that any router knows only which are the nodes greater and lesser than itself, but it cannot decide the relation between any two given nodes easily; that is why we need topological ordering.

この時点で、コンピューティングルータSは、MRTアイランドの各宛先のMRT-BlueネクストホップとMRT-Redネクストホップを認識しています。 SPTに沿った主要なネクストホップも知られています。宛先Dへの各プライマリネクストホップを決定するために残ります。MRTはプライマリネクストホップノードFを回避します。この計算は、各ノードyのy.blue_next_hops、y.red_next_hops、y.order_proxyなどのCompute_MRT_NextHopsのデータセットに依存します。 y.higher、y.lower、topo_orders。どのルーターも、自分よりも大きいノードと小さいノードのどちらかしか認識していないことを思い出してください。ただし、2つのノード間の関係を簡単に決定することはできません。これが、トポロジーの順序付けが必要な理由です。

For each primary next-hop node F to each destination D, S can call Select_Alternates(S, D, F, primary_intf) to determine whether to use the MRT-Blue or MRT-Red next hops as the alternate next hop(s) for that primary next hop. The algorithm is given in Figure 24 and discussed afterwards.

各宛先Dへの各プライマリネクストホップノードFについて、SはSelect_Alternates(S、D、F、primary_intf)を呼び出して、MRT-BlueまたはMRT-Redネクストホップを代替ネクストホップとして使用するかどうかを決定できます。そのプライマリネクストホップ。アルゴリズムは図24に示され、後で説明されています。

Select_Alternates_Internal(D, F, primary_intf, D_lower, D_higher, D_topo_order): if D_higher and D_lower if F.HIGHER and F.LOWER if F.topo_order < D_topo_order return USE_RED else return USE_BLUE if F.HIGHER return USE_RED if F.LOWER return USE_BLUE //F unordered wrt S return USE_RED_OR_BLUE

Select_Alternates_Internal(D、F、primary_intf、D_lower、D_higher、D_topo_order):if D_higher and D_lower if F.HIGHER and F.LOWER if F.topo_order <D_topo_order return USE_RED else return USE_BLUE if F.HIGHER return USE_RED IF return USE_BLUE return F.HIGHER return USE_RED IF return USE_BLUE return USE_BLUE if F.HIGHER return USE_RED USE FRED USE_RED USE_RED USE_RED USE_RED USE_RED USE_RED USE_RED USE_REDを返すUSE_REDが返された場合USE_REDが返された場合USE_REDが返された場合USE_REDが返された場合USE_REDが返された場合// F unordered wrt S return return USE_RED_OR_BLUE

else if D_higher if F.HIGHER and F.LOWER return USE_BLUE if F.LOWER return USE_BLUE if F.HIGHER if (F.topo_order > D_topo_order) return USE_BLUE if (F.topo_order < D_topo_order) return USE_RED //F unordered wrt S return USE_RED_OR_BLUE

else if D_higher if F.HIGHER and F.LOWER return USE_BLUE if F.LOWER return USE_BLUE if F.HIGHER if(F.topo_order> D_topo_order)return USE_BLUE if(F.topo_order <D_topo_order)return USE_RED // F unordered wrt S return USE_RED_OR_BLUE

else if D_lower if F.HIGHER and F.LOWER return USE_RED if F.HIGHER return USE_RED if F.LOWER if F.topo_order > D_topo_order return USE_BLUE

else if F.HIGHERとF.LOWERがD_lowerの場合、F.HIGHERがUSE_REDを返す場合はF.HIGHERを返し、F.LOWERがF.topo_order> D_topo_orderの場合はUSE_BLUEを返す

if F.topo_order < D_topo_order return USE_RED //F unordered wrt S return USE_RED_OR_BLUE

if F.topo_order <D_topo_order return USE_RED // F unordered wrt S return USE_RED_OR_BLUE

else //D is unordered wrt S if F.HIGHER and F.LOWER if primary_intf.OUTGOING and primary_intf.INCOMING return USE_RED_OR_BLUE if primary_intf.OUTGOING return USE_BLUE if primary_intf.INCOMING return USE_RED //primary_intf not in GADAG return USE_RED if F.LOWER return USE_RED if F.HIGHER return USE_BLUE //F unordered wrt S if F.topo_order > D_topo_order: return USE_BLUE else: return USE_RED

else // Dは、F.HIGHERの場合はSで順序付けされていません。primary_intf.OUTGOINGおよびprimary_intf.INCOMINGの場合はF.LOWERが返されます。primary_intf.OUTGOINGがUSE_BLUEを返す場合はprimary_intf.INCOMINGがUSE_REDを返す場合はUSE_RED // GADAGにないprimary_intfはUSE_REDを返します。 F.HIGHERがUSE_BLUEを返す場合はUSE_REDを返す// F.topo_order> D_topo_order>の場合はF順序付けなしのS:USE_BLUEを返すelse:USE_REDを返す

Select_Alternates(D, F, primary_intf) if not In_Common_Block(F, S) return PRIM_NH_IN_DIFFERENT_BLOCK if (D is F) or (D.order_proxy is F) return PRIM_NH_IS_D_OR_OP_FOR_D D_lower = D.order_proxy.LOWER D_higher = D.order_proxy.HIGHER D_topo_order = D.order_proxy.topo_order return Select_Alternates_Internal(D, F, primary_intf, D_lower, D_higher, D_topo_order)

Select_Alternates(D、F、primary_intf)でない場合In_Common_Block(F、S)はPRIM_NH_IN_DIFFERENT_BLOCKを返します(DがF)または(D.order_proxyがF)であればPRIM_NH_IS_D_OR_OP_FOR_D D_lower = D.order_proxy.LOWER D_highpr_HIGorder_D。 D.order_proxy.topo_order return Select_Alternates_Internal(D、F、primary_intf、D_lower、D_higher、D_topo_order)

      Figure 24: Select_Alternates() and Select_Alternates_Internal()
        

It is useful to first handle the case where F is also D, or F is the order proxy for D. In this case, only link protection is possible. The MRT that doesn't use the failed primary next hop is used. If both MRTs use the primary next hop, then the primary next hop must be a cut-link, so either MRT could be used but the set of MRT next hops must be pruned to avoid the failed primary next-hop interface. To indicate this case, Select_Alternates returns PRIM_NH_IS_D_OR_OP_FOR_D. Explicit pseudocode to handle the three sub-cases above is not provided.

FもDである場合、またはFがDのオーダープロキシである場合を最初に処理すると便利です。この場合、リンク保護のみが可能です。失敗したプライマリネクストホップを使用しないMRTが使用されます。両方のMRTがプライマリネクストホップを使用する場合、プライマリネクストホップはカットリンクである必要があるため、どちらのMRTも使用できますが、MRTネクストホップのセットをプルーニングして、プライマリネクストホップインターフェイスの障害を回避する必要があります。このケースを示すために、Select_AlternatesはPRIM_NH_IS_D_OR_OP_FOR_Dを返します。上記の3つのサブケースを処理する明示的な疑似コードは提供されていません。

The logic behind Select_Alternates_Internal() is described in Figure 25. As an example, consider the first case described in the table, where the D>>S and D<<S. If this is true, then either S or D must be the block root, R. If F>>S and F<<S, then S is the block root. So the blue path from S to D is the increasing path to D, and the red path S to D is the decreasing path to D. If the F.topo_order>D.topo_order, then either F is ordered higher than D or F is unordered with respect to D. Therefore, F is either on a decreasing path from S to D, or it is on neither an increasing nor a decreasing path from S to D. In either case, it is safe to take an increasing path from S to D to avoid F. We know that when S is R, the increasing path is the blue path, so it is safe to use the blue path to avoid F.

Select_Alternates_Internal()の背後にあるロジックを図25に示します。例として、表に記載されている最初のケースを考えてみます。ここで、D >> SおよびD << Sです。これが真である場合、SまたはDのいずれかがブロックルートRである必要があります。F>> SおよびF << Sの場合、Sはブロックルートです。つまり、SからDへの青いパスはDへの増加するパスであり、SからDへの赤いパスはDへの減少するパスです。したがって、FはSからDへの減少経路上にあるか、SからDへの増加経路にも減少経路にもありません。どちらの場合でも、Sから増加経路をとることは安全です。 Fを回避するためにDに変更します。SがRの場合、増加するパスは青色のパスであるため、青色のパスを使用してFを回避しても安全です。

If instead F.topo_order<D.topo_order, then either F is ordered lower than D, or F is unordered with respect to D. Therefore, F is either on an increasing path from S to D, or it is on neither an increasing nor a decreasing path from S to D. In either case, it is safe to take a decreasing path from S to D to avoid F. We know that when S is R, the decreasing path is the red path, so it is safe to use the red path to avoid F.

代わりにF.topo_order <D.topo_orderの場合、FはDよりも低い順序であるか、FはDに関して順序付けられていません。したがって、FはSからDへの増加するパス上にあるか、増加するパスにも増加するパスにもありません。 SからDへの減少するパス。どちらの場合でも、Fを回避するためにSからDへの減少するパスを使用しても安全です。SがRの場合、減少するパスは赤いパスであるため、安全に使用できます。 Fを避けるための赤い道

If F>>S or F<<S (but not both), then D is the block root. We then know that the blue path from S to D is the increasing path to R, and the red path is the decreasing path to R. When F>>S, we deduce that F is on an increasing path from S to R. So in order to avoid F, we use a decreasing path from S to R, which is the red path. Instead, when F<<S, we deduce that F is on a decreasing path from S to R. So in order to avoid F, we use an increasing path from S to R, which is the blue path.

F >> SまたはF << S(両方ではない)の場合、Dはブロックルートです。次に、SからDへの青いパスがRへの増加するパスであり、赤いパスがRへの減少するパスであることを知っています。F>> Sの場合、FがSからRへの増加するパス上にあると推定します。 Fを回避するために、SからRへの減少するパスを使用します。これは、赤いパスです。代わりに、F << Sの場合、FはSからRへの減少するパス上にあると推定します。したがって、Fを避けるために、SからRへの増加するパスを使用します。

All possible cases are systematically described in the same manner in the rest of the table.

すべての可能なケースは、表の残りの部分で同じ方法で体系的に説明されています。

+------+------------+------+------------------------------+------------+
| D    | MRT blue   | F    | additional      | F          | Alternate  |
| wrt  | and red    | wrt  | criteria        | wrt        |            |
| S    | path       | S    |                 | MRT        |            |
|      | properties |      |                 | (deduced)  |            |
+------+------------+------+-----------------+------------+------------+
| D>>S | Blue path: | F>>S | additional      | F on an    | Use Red    |
| and  | Increasing | only | criteria        | increasing | to avoid   |
| D<<S,| path to R. |      | not needed      | path from  | F          |
| D is | Red path:  |      |                 | S to R     |            |
| R,   | Decreasing +------+-----------------+------------+------------+
|      | path to R. | F<<S | additional      | F on a     | Use Blue   |
|      |            | only | criteria        | decreasing | to avoid   |
|      |            |      | not needed      | path from  | F          |
| or   |            |      |                 | S to R     |            |
|      |            +------+-----------------+------------+------------+
|      |            | F>>S | topo(F)>topo(D) | F on a     | Use Blue   |
| S is | Blue path: | and  | implies that    | decreasing | to avoid   |
| R    | Increasing | F<<S,| F>>D or F??D    | path from  | F          |
|      | path to D. |      |                 | S to D or  |            |
|      | Red path:  |      |                 | neither    |            |
|      | Decreasing |      +-----------------+------------+------------+
|      | path to D. |      | topo(F)<topo(D) | F on an    | Use Red    |
|      |            |      | implies that    | increasing | to avoid   |
|      |            |      | F<<D or F??D    | path from  | F          |
|      |            |      |                 | S to D or  |            |
|      |            |      |                 | neither    |            |
|      |            +------+-----------------+------------+------------+
|      |            | F??S | Can only occur  | F is on    | Use Red    |
|      |            |      | when link       | neither    | or Blue    |
|      |            |      | between         | increasing | to avoid   |
|      |            |      | F and S         | nor decr.  | F          |
|      |            |      | is marked       | path from  |            |
|      |            |      | MRT_INELIGIBLE  | S to D or R|            |
        
+------+------------+------+-----------------+------------+------------+
| D>>S | Blue path: | F<<S | additional      | F on       | Use Blue   |
| only | Increasing | only | criteria        | decreasing | to avoid   |
|      | shortest   |      | not needed      | path from  | F          |
|      | path from  |      |                 | S to R     |            |
|      | S to D.    +------+-----------------+------------+------------+
|      | Red path:  | F>>S | topo(F)>topo(D) | F on       | Use Blue   |
|      | Decreasing | only | implies that    | decreasing | to avoid   |
|      | shortest   |      | F>>D or F??D    | path from  | F          |
|      | path from  |      |                 | R to D     |            |
|      | S to R,    |      |                 | or         |            |
|      | then       |      |                 | neither    |            |
|      | decreasing |      +-----------------+------------+------------+
|      | shortest   |      | topo(F)<topo(D) | F on       | Use Red    |
|      | path from  |      | implies that    | increasing | to avoid   |
|      | R to D.    |      | F<<D or F??D    | path from  | F          |
|      |            |      |                 | S to D     |            |
|      |            |      |                 | or         |            |
|      |            |      |                 | neither    |            |
|      |            +------+-----------------+------------+------------+
|      |            | F>>S | additional      | F on Red   | Use Blue   |
|      |            | and  | criteria        |            | to avoid   |
|      |            | F<<S,| not needed      |            | F          |
|      |            | F is |                 |            |            |
|      |            | R    |                 |            |            |
|      |            +------+-----------------+------------+------------+
|      |            | F??S | Can only occur  | F is on    | Use Red    |
|      |            |      | when link       | neither    | or Blue    |
|      |            |      | between         | increasing | to avoid   |
|      |            |      | F and S         | nor decr.  | F          |
|      |            |      | is marked       | path from  |            |
|      |            |      | MRT_INELIGIBLE  | S to D or R|            |
        
+------+------------+------+-----------------+------------+------------+
| D<<S | Blue path: | F>>S | additional      | F on       | Use Red    |
| only | Increasing | only | criteria        | increasing | to avoid   |
|      | shortest   |      | not needed      | path from  | F          |
|      | path from  |      |                 | S to R     |            |
|      | S to R,    +------+-----------------+------------+------------+
|      | then       | F<<S | topo(F)>topo(D) | F on       | Use Blue   |
|      | increasing | only | implies that    | decreasing | to avoid   |
|      | shortest   |      | F>>D or F??D    | path from  | F          |
|      | path from  |      |                 | R to D     |            |
|      | R to D.    |      |                 | or         |            |
|      | Red path:  |      |                 | neither    |            |
|      | Decreasing |      +-----------------+------------+------------+
|      | shortest   |      | topo(F)<topo(D) | F on       | Use Red    |
|      | path from  |      | implies that    | increasing | to avoid   |
|      | S to D.    |      | F<<D or F??D    | path from  | F          |
|      |            |      |                 | S to D     |            |
|      |            |      |                 | or         |            |
|      |            |      |                 | neither    |            |
|      |            +------+-----------------+------------+------------+
|      |            | F>>S | additional      | F on Blue  | Use Red    |
|      |            | and  | criteria        |            | to avoid   |
|      |            | F<<S,| not             |            | F          |
|      |            | F is | needed          |            |            |
|      |            | R    |                 |            |            |
|      |            +------+-----------------+------------+------------+
|      |            | F??S | Can only occur  | F is on    | Use Red    |
|      |            |      | when link       | neither    | or Blue    |
|      |            |      | between         | increasing | to avoid   |
|      |            |      | F and S         | nor decr.  | F          |
|      |            |      | is marked       | path from  |            |
|      |            |      | MRT_INELIGIBLE  | S to D or R|            |
+------+------------+------+-----------------+------------+------------+
| D??S | Blue path: | F<<S | additional      | F on a     | Use Red    |
|      | Decr. from | only | criteria        | decreasing | to avoid   |
|      | S to first |      | not needed      | path from  | F          |
|      | node K<<D, |      |                 | S to K.    |            |
|      | then incr. +------+-----------------+------------+------------+
|      | to D.      | F>>S | additional      | F on an    | Use Blue   |
|      | Red path:  | only | criteria        | increasing | to avoid   |
|      | Incr. from |      | not needed      | path from  | F          |
|      | S to first |      |                 | S to L     |            |
|      | node L>>D, |      |                 |            |            |
|      | then decr. |      |                 |            |            |
        
|      |            +------+-----------------+------------+------------+
|      |            | F??S | topo(F)>topo(D) | F on decr. | Use Blue   |
|      |            |      | implies that    | path from  | to avoid   |
|      |            |      | F>>D or F??D    | L to D or  | F          |
|      |            |      |                 | neither    |            |
|      |            |      +-----------------+------------+------------+
|      |            |      | topo(F)<topo(D) | F on incr. | Use Red    |
|      |            |      | implies that    | path from  | to avoid   |
|      |            |      | F<<D or F??D    | K to D or  | F          |
|      |            |      |                 | neither    |            |
|      |            +------+-----------------+------------+------------+
|      |            | F>>S | GADAG link      | F on an    | Use Blue   |
|      |            | and  | direction       | incr. path | to avoid   |
|      |            | F<<S,| S->F            | from S     | F          |
|      |            | F is +-----------------+------------+------------+
|      |            | R    | GADAG link      | F on a     | Use Red    |
|      |            |      | direction       | decr. path | to avoid   |
|      |            |      | S<-F            | from S     | F          |
|      |            |      +-----------------+------------+------------+
|      |            |      | GADAG link      | Either F is the order   |
|      |            |      | direction       | proxy for D (case       |
|      |            |      | S<-->F          | already handled) or D   |
|      |            |      |                 | is in a different block |
|      |            |      |                 | from F, in which case   |
|      |            |      |                 | Red or Blue avoids F    |
|      |            |      +-----------------+-------------------------+
|      |            |      | S-F link not    | Relies on special       |
|      |            |      | in GADAG,       | construction of GADAG   |
|      |            |      | only when       | to demonstrate that     |
|      |            |      | S-F link is     | using Red avoids F      |
|      |            |      | MRT_INELIGIBLE  | (see text)              |
+------+------------+------+-----------------+-------------------------+
        

Determining MRT next hops and alternates based on the partial order and topological sort relationships between the source(S), destination(D), primary next hop(F), and block root(R). topo(N) indicates the topological sort value of node N. X??Y indicates that node X is unordered with respect to node Y. It is assumed that the case where F is D, or where F is the order proxy for D, has already been handled.

ソース(S)、宛先(D)、プライマリネクストホップ(F)、およびブロックルート(R)間の部分的な順序とトポロジカルソート関係に基づいて、MRTネクストホップと代替を決定します。 topo(N)は、ノードNのトポロジカルソート値を示します。X?? Yは、ノードXがノードYに対して順序付けされていないことを示します。FがDである場合、またはFがDの順序プロキシである場合を想定しています。すでに処理されています。

Figure 25: Determining MRT Next Hops and Alternates

図25:MRTネクストホップと代替の決定

The last case in Figure 25 requires additional explanation. The fact that the red path from S to D in this case avoids F relies on a special property of the GADAGs that we have constructed in this algorithm, a property not shared by all GADAGs in general. When D is unordered with respect to S, and F is the localroot for S, it can occur that the link between S and F is not in the GADAG only when that link has been marked MRT_INELIGIBLE. For an arbitrary GADAG, S doesn't have enough information based on the computed order relationships to determine if the red path or blue path will hit F (which is also the localroot) before hitting K or L, and making it safely to D. However, the GADAGs that we construct using the algorithm in this document are not arbitrary GADAGs. They have the additional property that incoming links to a localroot come from only one other node in the same block. This is a result of the method of construction. This additional property guarantees that the red path from S to D will never pass through the localroot of S. (That would require the localroot to play the role of L, the first node in the path ordered higher than D, which would in turn require the localroot to have two incoming links in the GADAG, which cannot happen.) Therefore, it is safe to use the red path to avoid F with these specially constructed GADAGs.

図25の最後のケースには、追加の説明が必要です。この場合、SからDへの赤いパスがFを回避するという事実は、このアルゴリズムで構築したGADAGの特別なプロパティに依存します。このプロパティは、すべてのGADAGで一般的に共有されるわけではありません。 DがSに関して順序付けられておらず、FがSのローカルルートである場合、そのリンクがMRT_INELIGIBLEとマークされている場合にのみ、SとFの間のリンクがGADAGにない場合があります。任意のGADAGの場合、Sには計算された順序関係に基づく十分な情報がないため、KまたはLにヒットする前に、赤のパスまたは青のパスがF(ローカルルートでもある)にヒットし、Dに安全に到達するかどうかを判断します。ただし、このドキュメントのアルゴリズムを使用して構築するGADAGは、任意のGADAGではありません。それらには、ローカルルートへの着信リンクが同じブロック内の他の1つのノードからのみ来るという追加のプロパティがあります。これは工法の結果です。この追加プロパティは、SからDへの赤いパスがSのローカルルートを通過しないことを保証します(ローカルルートがパスの最初のノードであるLの役割を果たす必要があるため、ローカルルートがDよりも高い順序で順番にlocalrootはGADAGに2つの着信リンクを設定します。これは発生しません。)したがって、これらの特別に構築されたGADAGでFを回避するために赤いパスを使用しても安全です。

As an example of how Select_Alternates_Internal() operates, consider the ADAG depicted in Figure 26 and first suppose that G is the source, D is the destination, and H is the failed next hop. Since D>>G, we need to compare H.topo_order and D.topo_order. Since D.topo_order>H.topo_order, D must be either higher than H or unordered with respect to H, so we should select the decreasing path towards the root. If, however, the destination were instead J, we must find that H.topo_order>J.topo_order, so we must choose the increasing Blue next hop to J, which is I. In the case, when instead the destination is C, we find that we need to first decrease to avoid using H, so the Blue, first decreasing then increasing, path is selected.

Select_Alternates_Internal()の動作の例として、図26に示すADAGを検討し、最初にGがソース、Dが宛先、Hが失敗したネクストホップであると想定します。 D >> Gなので、H.topo_orderとD.topo_orderを比較する必要があります。 D.topo_order> H.topo_orderであるため、DはHよりも高いか、Hに対して順序付けされていない必要があるため、ルートに向かって減少するパスを選択する必要があります。ただし、宛先がJである場合は、H.topo_order> J.topo_orderを見つける必要があるため、Jへの増加するBlueネクストホップ、つまりIを選択する必要があります。代わりに、宛先がCの場合、次のようになります。 Hの使用を回避するために、最初に減少する必要があることがわかります。そのため、最初に減少し、次に増加する青のパスが選択されます。

                             [E]<-[D]<-[H]<-[J]
                              |    ^    ^    ^
                              V    |    |    |
                             [R]  [C]  [G]->[I]
                              |    ^    ^    ^
                              V    |    |    |
                             [A]->[B]->[F]---|
        

Figure 26: ADAG Rooted at R for a 2-Connected Graph

図26:2接続グラフのRをルートとするADAG

5.9. Named Proxy-Nodes
5.9. 名前付きプロキシノード

As discussed in Section 11.2 of [RFC7812], it is necessary to find MRT-Blue and MRT-Red next hops and MRT-FRR alternates for named proxy-nodes. An example use case is for a router that is not part of that local MRT Island, when there is only partial MRT support in the domain.

[RFC7812]のセクション11.2で説明したように、MRT-BlueおよびMRT-Redのネクストホップと、名前付きプロキシノードのMRT-FRR代替を見つける必要があります。ユースケースの例は、ドメインにMRTサポートが部分的にしか存在しない場合に、そのローカルMRTアイランドの一部ではないルーターの場合です。

5.9.1. Determining Proxy-Node Attachment Routers
5.9.1. プロキシノードアタッチメントルーターの決定

Section 11.2 of [RFC7812] discusses general considerations for determining the two proxy-node attachment routers for a given proxy-node, corresponding to a prefix. A router in the MRT Island that advertises the prefix is a candidate for being a proxy-node attachment router, with the associated named-proxy-cost equal to the advertised cost to the prefix.

[RFC7812]のセクション11.2では、プレフィックスに対応する、特定のプロキシノードの2つのプロキシノードアタッチメントルーターを決定するための一般的な考慮事項について説明します。プレフィックスをアドバタイズするMRTアイランドのルーターは、プロキシノードアタッチメントルーターの候補であり、関連付けられたnamed-proxy-costはプレフィックスにアドバタイズされたコストと同じです。

An Island Border Router (IBR) is a router in the MRT Island that is connected to an Island Neighbor (IN), which is a router not in the MRT Island but in the same area/level. An (IBR,IN) pair is a candidate for being a proxy-node attachment router, if the shortest path from the IN to the prefix does not enter the MRT Island. A method for identifying such Loop-Free Island Neighbors (LFINs) is given below. The named-proxy-cost assigned to each (IBR, IN) pair is cost(IBR, IN) + D_opt(IN, prefix).

アイランドボーダールーター(IBR)は、アイランドネイバー(IN)に接続されているMRTアイランドのルーターです。これは、MRTアイランドではなく同じエリア/レベルにあるルーターです。 (IBR、IN)ペアは、INからプレフィックスへの最短パスがMRTアイランドに入らない場合、プロキシノード接続ルーターになる候補です。このようなループのないアイランドネイバー(LFIN)を識別する方法を以下に示します。各(IBR、IN)ペアに割り当てられる名前付きプロキシコストは、cost(IBR、IN)+ D_opt(IN、プレフィックス)です。

From the set of prefix-advertising routers and the set of IBRs with at least one LFIN, the two routers with the lowest named-proxy-cost are selected. Ties are broken based upon the lowest Router ID. For ease of discussion, the two selected routers will be referred to as proxy-node attachment routers.

プレフィックス広告ルーターのセットと、少なくとも1つのLFINを持つIBRのセットから、named-proxy-costが最も低い2つのルーターが選択されます。最小のルーターIDに基づいてタイが分割されます。説明を簡単にするために、選択した2つのルーターをプロキシノード接続ルーターと呼びます。

5.9.2. Computing If an Island Neighbor (IN) Is Loop-Free
5.9.2. アイランドネイバー(IN)にループがない場合の計算

As discussed above, the IN needs to be loop-free with respect to the whole MRT Island for the destination. This can be accomplished by running the usual SPF algorithm while keeping track of which shortest paths have passed through the MRT island. Pseudocode for this is shown in Figure 27. The Island_Marking_SPF() is run for each IN that needs to be evaluated for the loop-free condition, with the IN as the spf_root. Whether or not an IN is loop-free with respect to the MRT island can then be determined by evaluating node.PATH_HITS_ISLAND for each destination of interest.

上記で説明したように、INは宛先のMRTアイランド全体に対してループフリーである必要があります。これは、MRTアイランドを通過した最短パスを追跡しながら、通常のSPFアルゴリズムを実行することで実現できます。これの疑似コードを図27に示します。Island_Marking_SPF()は、INをspf_rootとして、ループのない状態を評価する必要がある各INに対して実行されます。 INがMRTアイランドに関してループフリーであるかどうかは、対象の宛先ごとにnode.PATH_HITS_ISLANDを評価することで判断できます。

Island_Marking_SPF(spf_root) Initialize spf_heap to empty Initialize nodes' spf_metric to infinity and next_hops to empty and PATH_HITS_ISLAND to false spf_root.spf_metric = 0 insert(spf_heap, spf_root) while (spf_heap is not empty) min_node = remove_lowest(spf_heap) foreach interface intf of min_node path_metric = min_node.spf_metric + intf.metric if path_metric < intf.remote_node.spf_metric intf.remote_node.spf_metric = path_metric if min_node is spf_root intf.remote_node.next_hops = make_list(intf) else intf.remote_node.next_hops = min_node.next_hops if intf.remote_node.IN_MRT_ISLAND intf.remote_node.PATH_HITS_ISLAND = true else intf.remote_node.PATH_HITS_ISLAND = min_node.PATH_HITS_ISLAND insert_or_update(spf_heap, intf.remote_node) else if path_metric == intf.remote_node.spf_metric if min_node is spf_root add_to_list(intf.remote_node.next_hops, intf) else add_list_to_list(intf.remote_node.next_hops, min_node.next_hops) if intf.remote_node.IN_MRT_ISLAND intf.remote_node.PATH_HITS_ISLAND = true else intf.remote_node.PATH_HITS_ISLAND = min_node.PATH_HITS_ISLAND

Island_Marking_SPF(spf_root)spf_heapを空に初期化し、ノードのspf_metricを無限大に、next_hopsを空に初期化し、PATH_HITS_ISLANDをfalseに初期化します。spf_root.spf_metric= 0 min_node path_metric = min_node.spf_metric + intf.metric if path_metric <intf.remote_node.spf_metric intf.remote_node.spf_metric = path_metric if min_node is spf_root intf.remote_node.next_hops = make_list(intf)else intf.remhop_nodes.exthop.exthop.node intf.remote_node.IN_MRT_ISLAND intf.remote_node.PATH_HITS_ISLAND = true else intf.remote_node.PATH_HITS_ISLAND = min_node.PATH_HITS_ISLAND insert_or_update(spf_heap、intf.remote_node)else if path_metric == intfnode_remote_node_remote_node_remote_node_remote_node_remote_node_remote_node next_hops、intf)else add_list_to_list(intf.remote_node.next_hops、min_node.next_hops)if intf.remote_node.IN_MRT_ISLAND intf.remote_node.PATH_HITS_I SLAND = true else intf.remote_node.PATH_HITS_ISLAND = min_node.PATH_HITS_ISLAND

Figure 27: Island_Marking_SPF() for Determining If an Island Neighbor Is Loop-Free

図27:アイランドネイバーにループがないかどうかを確認するIsland_Marking_SPF()

It is also possible that a given prefix is originated by a combination of non-island routers and island routers. The results of the Island_Marking_SPF() computation can be used to determine if the shortest path from an IN to reach that prefix hits the MRT Island. The shortest path for the IN to reach prefix P is determined by the total cost to reach prefix P, which is the sum of the cost for the IN to reach a prefix-advertising node and the cost with which that node advertises the prefix. The path with the minimum total cost to prefix P is chosen. If the prefix-advertising node for that minimum total cost path has PATH_HITS_ISLAND set to True, then the IN is not loop-free with respect to the MRT Island for reaching prefix P. If there are multiple minimum total cost paths to reach prefix P, then all of the prefix-advertising routers involved in the minimum total cost paths MUST have PATH_HITS_ISLAND set to False for the IN to be considered loop-free to reach P.

また、特定のプレフィックスが非アイランドルーターとアイランドルーターの組み合わせによって発信されている可能性もあります。 Island_Marking_SPF()計算の結果を使用して、INからそのプレフィックスに到達する最短パスがMRTアイランドに到達するかどうかを判断できます。 INがプレフィックスPに到達するための最短パスは、プレフィックスPに到達するための総コストによって決まります。これは、INがプレフィックス広告ノードに到達するためのコストと、そのノードがプレフィックスをアドバタイズするためのコストの合計です。プレフィックスPへの最小合計コストを持つパスが選択されます。その最小総コストパスのプレフィックスアドバタイジングノードでPATH_HITS_ISLANDがTrueに設定されている場合、プレフィックスPに到達するためのMRTアイランドに関してINはループフリーではありません。プレフィックスPに到達する複数の最小総コストパスがある場合、次に、INがループフリーでPに到達すると見なされるためには、最小総コストパスに関係するすべてのプレフィックス広告ルーターでPATH_HITS_ISLANDをFalseに設定する必要があります。

Note that there are other computations that could be used to determine if paths from a given IN _might_ pass through the MRT Island for a given prefix or destination. For example, a previous draft version of this document specified running the SPF algorithm on modified topology that treats the MRT Island as a single node (with intra-island links set to zero cost) in order to provide input to computations to determine if the path from IN to non-island destination hits the MRT Island in this modified topology. This computation is enough to guarantee that a path will not hit the MRT Island in the original topology. However, it is possible that a path that is disqualified for hitting the MRT Island in the modified topology will not actually hit the MRT Island in the original topology. The algorithm described in Island_Marking_SPF() above does not modify the original topology, and will only disqualify a path if the actual path does in fact hit the MRT Island.

特定のINからのパスが、特定のプレフィックスまたは宛先のMRTアイランドを通過するかどうかを判断するために使用できる他の計算があることに注意してください。たとえば、このドキュメントの以前のドラフトバージョンでは、MRTアイランドを単一ノードとして処理する変更されたトポロジでSPFアルゴリズムを実行することを指定しました(アイランド内リンクがゼロコストに設定されている)。この変更されたトポロジでは、INから非アイランドの宛先へのMRTアイランドがヒットします。この計算は、パスが元のトポロジのMRTアイランドにヒットしないことを保証するのに十分です。ただし、変更されたトポロジでMRTアイランドにヒットするのに不適格なパスが、実際には元のトポロジでMRTアイランドにヒットしない可能性があります。上記のIsland_Marking_SPF()で説明したアルゴリズムは、元のトポロジを変更せず、実際のパスが実際にMRTアイランドにヒットした場合にのみパスを失格にします。

Since all routers need to come to the same conclusion about which routers qualify as LFINs, this specification requires that all routers computing LFINs MUST use an algorithm whose result is identical to that of the Island_Marking_SPF() in Figure 27.

すべてのルーターがどのルーターがLFINとして適格であるかについて同じ結論に達する必要があるため、この仕様では、LFINを計算するすべてのルーターが、図27のIsland_Marking_SPF()と同じ結果のアルゴリズムを使用する必要があることを要求します。

5.9.3. Computing MRT Next Hops for Proxy-Nodes
5.9.3. プロキシノードのMRTネクストホップの計算

Determining the MRT next hops for a proxy-node in the degenerate case where the proxy-node is attached to only one node in the GADAG is trivial, as all needed information can be derived from that proxy-node attachment router. If there are multiple interfaces connecting the proxy-node to the single proxy-node attachment router, then some can be assigned to MRT-Red and others to MRT_Blue.

プロキシノードがGADAG内の1つのノードにのみ接続されている縮退の場合、プロキシノードのMRTネクストホップを決定するのは簡単です。必要な情報はすべてプロキシノード接続ルーターから取得できるためです。プロキシノードを単一のプロキシノードアタッチメントルーターに接続する複数のインターフェースがある場合は、一部をMRT-Redに割り当て、その他をMRT_Blueに割り当てることができます。

Now, consider the proxy-node P that is attached to two proxy-node attachment routers. The pseudocode for Select_Proxy_Node_NHs(P,S) in Figure 28 specifies how a computing-router S MUST compute the MRT red and blue next hops to reach proxy-node P. The proxy-node attachment router with the lower value of mrt_node_id (as defined in Figure 15) is assigned to X, and the other proxy-node attachment router is assigned to Y. We will be using the relative order of X,Y, and S in the partial order defined by the GADAG to determine the MRT red and blue next hops to reach P, so we also define A and B as the order proxies for X and Y, respectively, with respect to S. The order proxies for all nodes with respect to S were already computed in Compute_MRT_NextHops().

ここで、2つのプロキシノード接続ルーターに接続されているプロキシノードPについて考えます。図28のSelect_Proxy_Node_NHs(P、S)の疑似コードは、コンピューティングルーターSがMRT赤と青のネクストホップを計算して、プロキシノードPに到達する方法を指定する必要があります。mrt_node_idの値が小さいプロキシノード接続ルーター図15)はXに割り当てられ、他のプロキシノードアタッチメントルーターはYに割り当てられています。X、Y、Sの相対的な順序をGADAGで定義された部分的な順序で使用して、MRT赤とPに到達するための青いネクストホップ。したがって、Sに関して、AとBをそれぞれXとYの順序プロキシとして定義します。Sに関するすべてのノードの順序プロキシは、Compute_MRT_NextHops()で既に計算されています。

 def Select_Proxy_Node_NHs(P,S):
     if P.pnar1.node.node_id < P.pnar2.node.node_id:
         X = P.pnar1.node
         Y = P.pnar2.node
     else:
         X = P.pnar2.node
         Y = P.pnar1.node
     P.pnar_X = X
     P.pnar_Y = Y
     A = X.order_proxy
     B = Y.order_proxy
     if (A is S.localroot
         and B is S.localroot):
         // case 1.0
         Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
         Copy_List_Items(P.red_next_hops, Y.red_next_hops)
         return
     if (A is S.localroot
         and B is not S.localroot):
         // case 2.0
         if B.LOWER:
             // case 2.1
             Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
             Copy_List_Items(P.red_next_hops, Y.red_next_hops)
             return
         if B.HIGHER:
             // case 2.2
             Copy_List_Items(P.blue_next_hops, X.red_next_hops)
             Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
             return
         else:
             // case 2.3
             Copy_List_Items(P.blue_next_hops, X.red_next_hops)
             Copy_List_Items(P.red_next_hops, Y.red_next_hops)
             return
     if (A is not S.localroot
         and B is S.localroot):
         // case 3.0
         if A.LOWER:
             // case 3.1
             Copy_List_Items(P.blue_next_hops, X.red_next_hops)
             Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
             return
         if A.HIGHER:
             // case 3.2
             Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
             Copy_List_Items(P.red_next_hops, Y.red_next_hops)
             return
        
         else:
             // case 3.3
             Copy_List_Items(P.blue_next_hops, X.red_next_hops)
             Copy_List_Items(P.red_next_hops, Y.red_next_hops)
             return
     if (A is not S.localroot
         and B is not S.localroot):
         // case 4.0
         if (S is A.localroot or S is B.localroot):
             // case 4.05
             if A.topo_order < B.topo_order:
                 // case 4.05.1
                 Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                 return
             else:
                 // case 4.05.2
                 Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                 return
         if A.LOWER:
             // case 4.1
             if B.HIGHER:
                 // case 4.1.1
                 Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                 return
             if B.LOWER:
                 // case 4.1.2
                 if A.topo_order < B.topo_order:
                     // case 4.1.2.1
                     Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                     Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                     return
                 else:
                     // case 4.1.2.2
                     Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                     Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                     return
             else:
                 // case 4.1.3
                 Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                 return
         if A.HIGHER:
             // case 4.2
             if B.HIGHER:
                 // case 4.2.1
                 if A.topo_order < B.topo_order:
                     // case 4.2.1.1
                     Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                     Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                     return
                 else:
                     // case 4.2.1.2
                     Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                     Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                     return
             if B.LOWER:
                 // case 4.2.2
                 Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                 return
             else:
                 // case 4.2.3
                 Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                 return
         else:
             // case 4.3
             if B.LOWER:
                 // case 4.3.1
                 Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                 return
             if B.HIGHER:
                 // case 4.3.2
                 Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                 Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                 return
             else:
                 // case 4.3.3
                 if A.topo_order < B.topo_order:
                     // case 4.3.3.1
                     Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                     Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                     return
        

else: // case 4.3.3.2 Copy_List_Items(P.blue_next_hops, X.red_next_hops) Copy_List_Items(P.red_next_hops, Y.blue_next_hops) return assert(False)

else://ケース4.3.3.2 Copy_List_Items(P.blue_next_hops、X.red_next_hops)Copy_List_Items(P.red_next_hops、Y.blue_next_hops)return assert(False)

Figure 28: Select_Proxy_Node_NHs()

図28:Select_Proxy_Node_NHs()

It is useful to understand up front that the blue next hops to reach proxy-node P produced by Select_Proxy_Node_NHs() will always be the next hops that reach proxy-node attachment router X, while the red next hops to reach proxy-node P will always be the next hops that reach proxy-node attachment router Y. This is different from the red and blue next hops produced by Compute_MRT_NextHops() where, for example, blue next hops to a destination that is ordered with respect to the source will always correspond to an INCREASING next hop on the GADAG. The exact choice of which next hops chosen by Select_Proxy_Node_NHs() as the blue next hops to reach P (which will necessarily go through X on its way to P) does depend on the GADAG, but the relationship is more complex than was the case with Compute_MRT_NextHops().

Select_Proxy_Node_NHs()によって生成されたプロキシノードPに到達する青いネクストホップは常にプロキシノードアタッチメントルーターXに到達するネクストホップであり、プロキシノードPに到達する赤いネクストホップは常に常にプロキシノード接続ルーターYに到達するネクストホップになります。これは、Compute_MRT_NextHops()によって生成される赤と青のネクストホップとは異なります。たとえば、送信元に対して順序付けられた宛先への青のネクストホップは常にGADAGの増加する次のホップに対応します。 Select_Proxy_Node_NHs()がPに到達するための青いネクストホップとして選択するネクストホップ(これは必ずPへの途中でXを通過する)の正確な選択はGADAGに依存しますが、関係はGADAGの場合よりも複雑です。 Compute_MRT_NextHops()。

There are 21 different relative order relationships between A, B, and S that Select_Proxy_Node_NHs() uses to determine red and blue next hops to P. This document does not attempt to provide an exhaustive description of each case considered in Select_Proxy_Node_NHs(). Instead, we provide a high-level overview of the different cases, and we consider a few cases in detail to give an example of the reasoning that can be used to understand each case.

Select_Proxy_Node_NHs()がPへの赤と青のネクストホップを決定するために使用するA、B、Sの間には21の異なる相対順序関係があります。このドキュメントは、Select_Proxy_Node_NHs()で考慮される各ケースの完全な説明を提供することを試みません。代わりに、さまざまなケースの概要を提供し、いくつかのケースを詳細に検討して、各ケースを理解するために使用できる理由の例を示します。

At the highest level, Select_Proxy_Node_NHs() distinguishes between four different cases depending on whether or not A or B is the localroot for S. For example, for case 4.0, neither A nor B is the localroot for S. Case 4.05 addresses the case where S is the localroot for either A or B, while cases 4.1, 4.2, and 4.3 address the cases where A is ordered lower than S, A is ordered higher than S, or A is unordered with respect to S on the GADAG. In general, each of these cases is then further subdivided into whether or not B is ordered lower than S, B is ordered higher than S, or B is unordered with respect to S. In some cases, we also need a further level of discrimination, where we use the topological sort order of A with respect to B.

最高レベルでは、Select_Proxy_Node_NHs()は、AまたはBがSのローカルルートであるかどうかに応じて、4つの異なるケースを区別します。たとえば、ケース4.0の場合、AもBもSのローカルルートではありません。ケース4.05は、 SはAまたはBのローカルルートですが、ケース4.1、4.2、および4.3は、AがSよりも低い順序で並べられている場合、AがSよりも高い順序で並べられている場合、またはAがGADAGのSに関して順序付けされていない場合に対応しています。一般的に、これらの各ケースはさらに、BがSよりも低い順序であるか、BがSよりも高い順序であるか、またはBがSに対して無順序であるかどうかにさらに細分されます。場合によっては、さらに高いレベルの識別も必要です。 、ここではBに関してAのトポロジカルソート順を使用します。

As a detailed example, let's consider case 4.1 and all of its sub-cases, and explain why the red and blue next hops to reach P are chosen as they are in Select_Proxy_Node_NHs(). In case 4.1, neither A nor B is the localroot for S, S is not the localroot for A or B, and A is ordered lower than S on the GADAG. In this situation, we know that the red path to reach X (as computed in Compute_MRT_NextHops()) will follow DECREASING next hops towards A, while the blue path to reach X will follow INCREASING next hops to the localroot, and then INCREASING next hops to A.

詳細な例として、ケース4.1とそのすべてのサブケースを検討し、Pに到達するための赤と青のネクストホップがSelect_Proxy_Node_NHs()で選択されている理由を説明します。 4.1の場合、AもBもSのローカルルートではなく、SはAまたはBのローカルルートではなく、GADAGではAはSよりも低い順序で並べられます。この状況では、Xに到達するための赤いパス(Compute_MRT_NextHops()で計算される)はAへのネクストホップの減少に従いますが、Xに到達する青いパスはローカルルートへのネクストホップの増加をたどり、次のホップを増加します。 Aに

Now consider sub-case 4.1.1 where B is ordered higher than S. In this situation, we know that the blue path to reach Y will follow INCREASING next hops towards B, while the red next hops to reach Y will follow DECREASING next hops to the localroot, and then DECREASING next hops to B. So, to reach X and Y by two disjoint paths, we can choose the red next hops to X and the blue next hops to Y. We have chosen the convention that blue next hops to P are those that pass through X, and red next hops to P are those that pass through Y, so we can see that case 4.1.1 produces the desired result. Choosing blue to X and red to Y does not produce disjoint paths because the paths intersect at least at the localroot.

次に、BがSよりも高い順序でサブケース4.1.1を検討します。この状況では、Yに到達する青いパスはBへの次のホップが増加し、Yに到達する赤い次ホップは次のホップが減少することがわかります。ローカルルートに移動し、次にBへのネクストホップを減少させます。したがって、2つのばらばらのパスでXとYに到達するには、Xへの赤のネクストホップとYへの青のネクストホップを選択できます。 PへのパスはXを通過するものであり、Pへの赤いネクストホップはYを通過するものであるため、ケース4.1.1が望ましい結果をもたらすことがわかります。パスが少なくともローカルルートで交差しているため、青からXおよび赤からYを選択しても分離パスは生成されません。

Now consider sub-case 4.1.2 where B is ordered lower than S. In this situation, we know that the red path to reach Y will follow DECREASING next hops towards B, while the BLUE next hops to reach Y will follow INCREASING next hops to the localroot, and then INCREASING next hops to A. The choice here is more difficult than in 4.1.1 because A and B are both on the DECREASING path from S towards the localroot. We want to use the direct DECREASING(red) path to the one that is nearer to S on the GADAG. We get this extra information by comparing the topological sort order of A and B. If A.topo_order<B.topo_order, then we use red to Y and blue to X, since the red path to Y will DECREASE to B without hitting A, and the blue path to X will INCREASE to A without hitting B. Instead, if A.topo_order>B.topo_order, then we use red to X and blue to Y.

次に、BがSよりも低い順序でサブケース4.1.2を検討します。この状況では、Yに到達する赤いパスはBへのネクストホップを減少させ、Yに到達する青色のネクストホップはネクストホップを増加させることがわかります。 AとBの両方がSからローカルルートに向かう減少パス上にあるため、ここでの選択は4.1.1よりも困難です。 GADAGのSに最も近いパスへの直接のDECREASING(red)パスを使用します。 AとBのトポロジカルソート順を比較することによって、この追加情報を取得します。A.topo_order<B.topo_orderの場合、Yへの赤いパスはAにヒットせずにBに減少するため、赤からYおよび青からXを使用します。 Xへの青のパスはBにヒットすることなくAに増加します。代わりに、A.topo_order> B.topo_orderの場合、赤からX、青からYを使用します。

Note that when A is unordered with respect to B, the result of comparing A.topo_order with B.topo_order could be greater than or less than. In this case, the result doesn't matter because either choice (red to Y and blue to X or red to X and blue to Y) would work. What is required is that all nodes in the network give the same result when comparing A.topo_order with B.topo_order. This is guaranteed by having all nodes run the same algorithm (Run_Topological_Sort_GADAG()) to compute the topological sort order.

AがBに関して順序付けされていない場合、A.topo_orderとB.topo_orderを比較した結果は、大きくなる場合と小さくなる場合があることに注意してください。この場合、どちらの選択(赤からYおよび青からXまたは赤からXおよび青からY)でも機能するため、結果は重要ではありません。必要なのは、A.topo_orderとB.topo_orderを比較すると、ネットワーク内のすべてのノードで同じ結果が得られることです。これは、すべてのノードが同じアルゴリズム(Run_Topological_Sort_GADAG())を実行してトポロジカルソート順を計算することで保証されます。

Finally, we consider case 4.1.3, where B is unordered with respect to S. In this case, the blue path to reach Y will follow the DECREASING next hops towards the localroot until it reaches some node (K) which is ordered less than B, after which it will take INCREASING next hops to B. The red path to reach Y will follow the INCREASING next hops towards the localroot until it reaches some node (L) which is ordered greater than B, after which it will take DECREASING next hops to B.

最後に、ケース4.1.3を検討します。ここで、BはSに関して順序付けられていません。この場合、Yに到達するための青いパスは、ローカルルートに向かう次のホップの減少に従い、順序が小さいノード(K)に到達するまで続きます。 B、その後、Bへのネクストホップが増加します。Yに到達するための赤いパスは、Bよりも大きい順序であるノード(L)に到達するまで、ローカルルートに向かって増加し、ネクストホップをたどります。その後、次に減少します。 Bにホップ

Both K and A are reached by DECREASING from S, but we don't have information about whether or not that DECREASING path will hit K or A first. Instead, we do know that the INCREASING path from S will hit L before reaching A. Therefore, we use the red path to reach Y and the red path to reach X.

KとAの両方にSからDECREASINGが到達しますが、そのDECREASINGパスが最初にKまたはAにヒットするかどうかについての情報はありません。代わりに、SからのINCREASINGパスがAに到達する前にLにヒットすることを知っています。したがって、Yに到達するために赤いパスを使用し、Xに到達するために赤いパスを使用します。

Similar reasoning can be applied to understand the other 17 cases used in Select_Proxy_Node_NHs(). However, cases 2.3 and 3.3 deserve special attention because the correctness of the solution for these two cases relies on a special property of the GADAGs that we have constructed in this algorithm, a property not shared by all GADAGs in general. Focusing on case 2.3, we consider the case where A is the localroot for S, while B is not, and B is unordered with respect to S. The red path to X DECREASES from S to the localroot A, while the blue path to X INCREASES from S to the localroot A. The blue path to Y DECREASES towards the localroot A until it reaches some node (K) which is ordered less than B, after which the path INCREASES to B. The red path to Y INCREASES towards the localroot A until it reaches some node (L) which is ordered greater than B, after which the path DECREASES to B. It can be shown that for an arbitrary GADAG, with only the ordering relationships computed so far, we don't have enough information to choose a pair of paths to reach X and Y that are guaranteed to be disjoint. In some topologies, A will play the role of K, the first node ordered less than B on the blue path to Y. In other topologies, A will play the role of L, the first node ordered greater than B on the red path to Y. The basic problem is that we cannot distinguish between these two cases based on the ordering relationships.

同様の推論を適用して、Select_Proxy_Node_NHs()で使用される他の17のケースを理解することができます。ただし、これらの2つのケースのソリューションの正確さは、このアルゴリズムで構築したGADAGの特別なプロパティに依存しているため、ケース2.3と3.3は特別な注意に値します。ケース2.3に焦点を当てて、AがSのローカルルートであり、Bはそうではなく、BがSに関して順序付けされていない場合を考えます。Xへの赤いパスはSからローカルルートAに減少し、Xへの青いパスは減少します。 SからローカルルートAまで増加します。Yへの青いパスは、ローカルルートAに向かって減少し、Bよりも小さい順序で並べられたノード(K)に到達します。その後、パスはBに増加します。Yへの赤いパスは、ローカルルートに向かって増加します。 Aは、Bよりも大きい順序のノード(L)に到達するまで続きます。その後、パスはBに減少します。これまでに計算された順序関係だけで、任意のGADAGの場合、十分な情報がないことが示されます。互いに素であることが保証されているXとYに到達するパスのペアを選択する。一部のトポロジでは、AはKの役割を果たし、最初のノードはYへの青いパスでBよりも小さい順序で並べられます。他のトポロジでは、AはLの役割を果たし、最初のノードは赤いパスでBよりも大きい順序で並べられますY.基本的な問題は、順序関係に基づいてこれら2つのケースを区別できないことです。

As discussed Section 5.8, the GADAGs that we construct using the algorithm in this document are not arbitrary GADAGs. They have the additional property that incoming links to a localroot come from only one other node in the same block. This is a result of the method of construction. This additional property guarantees that localroot A will never play the role of L in the red path to Y, since L must have at least two incoming links from different nodes in the same block in the GADAG. This, in turn, allows Select_Proxy_Node_NHs() to choose the red path to Y and the red path to X as the disjoint MRT paths to reach P.

セクション5.8で説明したように、このドキュメントのアルゴリズムを使用して構築するGADAGは任意のGADAGではありません。それらには、ローカルルートへの着信リンクが同じブロック内の他の1つのノードからのみ来るという追加のプロパティがあります。これは工法の結果です。 LにはGADAG内の同じブロック内の異なるノードからの少なくとも2つの着信リンクが必要であるため、この追加のプロパティは、localroot AがYへの赤いパスでLの役割を果たすことはないことを保証します。これにより、Select_Proxy_Node_NHs()は、Yへの赤いパスとXへの赤いパスを、Pに到達する分離されたMRTパスとして選択できるようになります。

5.9.4. Computing MRT Alternates for Proxy-Nodes
5.9.4. プロキシノードの代替MRTの計算

After finding the red and the blue next hops for a given proxy-node P, it is necessary to know which one of these to use in the case of failure. This can be done by Select_Alternates_Proxy_Node(), as shown in the pseudocode in Figure 29.

所定のプロキシノードPの赤と青のネクストホップを見つけた後、障害が発生した場合にこれらのどれを使用するかを知る必要があります。これは、図29の疑似コードに示すように、Select_Alternates_Proxy_Node()によって実行できます。

def Select_Alternates_Proxy_Node(P,F,primary_intf): S = primary_intf.local_node X = P.pnar_X Y = P.pnar_Y A = X.order_proxy B = Y.order_proxy if F is A and F is B: return 'PRIM_NH_IS_OP_FOR_BOTH_X_AND_Y' if F is A: return 'USE_RED' if F is B: return 'USE_BLUE'

def Select_Alternates_Proxy_Node(P、F、primary_intf):S = primary_intf.local_node X = P.pnar_X Y = P.pnar_Y A = X.order_proxy B = Y.order_proxy if F is A and F is B:return 'PRIM_NH_IS_OP_FOR_BOTH_X_AND_Y' is A:FがBの場合は「USE_RED」を返す:「USE_BLUE」を返す

if not In_Common_Block(A, B): if In_Common_Block(F, A): return 'USE_RED' elif In_Common_Block(F, B): return 'USE_BLUE' else: return 'USE_RED_OR_BLUE' if (not In_Common_Block(F, A) and not In_Common_Block(F, A) ): return 'USE_RED_OR_BLUE'

In_Common_Block(A、B)でない場合:if In_Common_Block(F、A):return 'USE_RED' elif In_Common_Block(F、B):return 'USE_BLUE' else:return 'USE_RED_OR_BLUE' if(not In_Common_Block(F、A)and not In_Common_Block(F、A)): 'USE_RED_OR_BLUE'を返す

      alt_to_X = Select_Alternates(X, F, primary_intf)
      alt_to_Y = Select_Alternates(Y, F, primary_intf)
        
      if (alt_to_X == 'USE_RED_OR_BLUE'
          and alt_to_Y == 'USE_RED_OR_BLUE'):
          return 'USE_RED_OR_BLUE'
      if alt_to_X == 'USE_RED_OR_BLUE':
          return 'USE_BLUE'
      if alt_to_Y == 'USE_RED_OR_BLUE':
          return 'USE_RED'
        
      if (A is S.localroot
          and B is S.localroot):
          // case 1.0
          if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
              return 'USE_RED_OR_BLUE'
          if alt_to_X == 'USE_BLUE':
              return 'USE_BLUE'
          if alt_to_Y == 'USE_RED':
              return 'USE_RED'
          assert(False)
      if (A is S.localroot
          and B is not S.localroot):
          // case 2.0
          if B.LOWER:
              // case 2.1
              if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
                  return 'USE_RED_OR_BLUE'
              if alt_to_X == 'USE_BLUE':
                  return 'USE_BLUE'
              if alt_to_Y == 'USE_RED':
                  return 'USE_RED'
              assert(False)
          if B.HIGHER:
              // case 2.2
              if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                  return 'USE_RED_OR_BLUE'
              if alt_to_X == 'USE_RED':
                  return 'USE_BLUE'
              if alt_to_Y == 'USE_BLUE':
                  return 'USE_RED'
              assert(False)
          else:
              // case 2.3
              if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_RED'):
                  return 'USE_RED_OR_BLUE'
              if alt_to_X == 'USE_RED':
                  return 'USE_BLUE'
              if alt_to_Y == 'USE_RED':
                  return 'USE_RED'
              assert(False)
      if (A is not S.localroot
          and B is S.localroot):
          // case 3.0
          if A.LOWER:
              // case 3.1
              if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                  return 'USE_RED_OR_BLUE'
              if alt_to_X == 'USE_RED':
                  return 'USE_BLUE'
              if alt_to_Y == 'USE_BLUE':
                  return 'USE_RED'
              assert(False)
          if A.HIGHER:
              // case 3.2
              if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
                  return 'USE_RED_OR_BLUE'
              if alt_to_X == 'USE_BLUE':
                  return 'USE_BLUE'
              if alt_to_Y == 'USE_RED':
                  return 'USE_RED'
              assert(False)
        
          else:
              // case 3.3
              if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_RED'):
                  return 'USE_RED_OR_BLUE'
              if alt_to_X == 'USE_RED':
                  return 'USE_BLUE'
              if alt_to_Y == 'USE_RED':
                  return 'USE_RED'
              assert(False)
      if (A is not S.localroot
          and B is not S.localroot):
          // case 4.0
          if (S is A.localroot or S is B.localroot):
              // case 4.05
              if A.topo_order < B.topo_order:
                  // case 4.05.1
                  if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
                      return 'USE_RED_OR_BLUE'
                  if alt_to_X == 'USE_BLUE':
                      return 'USE_BLUE'
                  if alt_to_Y == 'USE_RED':
                      return 'USE_RED'
                  assert(False)
              else:
                  // case 4.05.2
                  if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                      return 'USE_RED_OR_BLUE'
                  if alt_to_X == 'USE_RED':
                      return 'USE_BLUE'
                  if alt_to_Y == 'USE_BLUE':
                      return 'USE_RED'
                  assert(False)
          if A.LOWER:
              // case 4.1
              if B.HIGHER:
                  // case 4.1.1
                  if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                      return 'USE_RED_OR_BLUE'
                  if alt_to_X == 'USE_RED':
                      return 'USE_BLUE'
                  if alt_to_Y == 'USE_BLUE':
                      return 'USE_RED'
                  assert(False)
              if B.LOWER:
                  // case 4.1.2
                  if A.topo_order < B.topo_order:
                      // case 4.1.2.1
                      if (alt_to_X == 'USE_BLUE'
        
                          and alt_to_Y == 'USE_RED'):
                          return 'USE_RED_OR_BLUE'
                      if alt_to_X == 'USE_BLUE':
                          return 'USE_BLUE'
                      if alt_to_Y == 'USE_RED':
                          return 'USE_RED'
                      assert(False)
                  else:
                      // case 4.1.2.2
                      if (alt_to_X == 'USE_RED'
                          and alt_to_Y == 'USE_BLUE'):
                          return 'USE_RED_OR_BLUE'
                      if alt_to_X == 'USE_RED':
                          return 'USE_BLUE'
                      if alt_to_Y == 'USE_BLUE':
                          return 'USE_RED'
                      assert(False)
              else:
                  // case 4.1.3
                  if (F.LOWER and not F.HIGHER
                      and F.topo_order > A.topo_order):
                      // case 4.1.3.1
                      return 'USE_RED'
                  else:
                      // case 4.1.3.2
                      return 'USE_BLUE'
          if A.HIGHER:
              // case 4.2
              if B.HIGHER:
                  // case 4.2.1
                  if A.topo_order < B.topo_order:
                      // case 4.2.1.1
                      if (alt_to_X == 'USE_BLUE'
                          and alt_to_Y == 'USE_RED'):
                          return 'USE_RED_OR_BLUE'
                      if alt_to_X == 'USE_BLUE':
                          return 'USE_BLUE'
                      if alt_to_Y == 'USE_RED':
                          return 'USE_RED'
                      assert(False)
                  else:
                      // case 4.2.1.2
                      if (alt_to_X == 'USE_RED'
                          and alt_to_Y == 'USE_BLUE'):
                          return 'USE_RED_OR_BLUE'
                      if alt_to_X == 'USE_RED':
                          return 'USE_BLUE'
                      if alt_to_Y == 'USE_BLUE':
        
                          return 'USE_RED'
                      assert(False)
              if B.LOWER:
                  // case 4.2.2
                  if (alt_to_X == 'USE_BLUE'
                      and alt_to_Y == 'USE_RED'):
                      return 'USE_RED_OR_BLUE'
                  if alt_to_X == 'USE_BLUE':
                      return 'USE_BLUE'
                  if alt_to_Y == 'USE_RED':
                      return 'USE_RED'
                  assert(False)
              else:
                  // case 4.2.3
                  if (F.HIGHER and not F.LOWER
                      and F.topo_order < A.topo_order):
                      return 'USE_RED'
                  else:
                      return 'USE_BLUE'
          else:
              // case 4.3
              if B.LOWER:
                  // case 4.3.1
                  if (F.LOWER and not F.HIGHER
                      and F.topo_order > B.topo_order):
                      return 'USE_BLUE'
                  else:
                      return 'USE_RED'
              if B.HIGHER:
                  // case 4.3.2
                  if (F.HIGHER and not F.LOWER
                      and F.topo_order < B.topo_order):
                      return 'USE_BLUE'
                  else:
                      return 'USE_RED'
              else:
                  // case 4.3.3
                  if A.topo_order < B.topo_order:
                      // case 4.3.3.1
                      if (alt_to_X == 'USE_BLUE'
                          and alt_to_Y == 'USE_RED'):
                          return 'USE_RED_OR_BLUE'
                      if alt_to_X == 'USE_BLUE':
                          return 'USE_BLUE'
                      if alt_to_Y == 'USE_RED':
                          return 'USE_RED'
                      assert(False)
        
                  else:
                      // case 4.3.3.2
                      if (alt_to_X == 'USE_RED'
                          and alt_to_Y == 'USE_BLUE'):
                          return 'USE_RED_OR_BLUE'
                      if alt_to_X == 'USE_RED':
                          return 'USE_BLUE'
                      if alt_to_Y == 'USE_BLUE':
                          return 'USE_RED'
                      assert(False)
      assert(False)
        

Figure 29: Select_Alternates_Proxy_Node()

図29:Select_Alternates_Proxy_Node()

Select_Alternates_Proxy_Node(P,F,primary_intf) determines whether it is safe to use the blue path to P (which goes through X), the red path to P (which goes through Y), or either, when the primary_intf to node F (and possibly node F) fails. The basic approach is to run Select_Alternates(X,F,primary_intf) and Select_Alternates(Y,F,primary_intf) to determine which of the two MRT paths to X and which of the two MRT paths to Y is safe to use in the event of the failure of F. In general, we will find that if it is safe to use a particular path to X or Y when F fails, and Select_Proxy_Node_NHs() used that path when constructing the red or blue path to reach P, then it will also be safe to use that path to reach P when F fails. This rule has one exception which is covered below. First, we give a concrete example of how Select_Alternates_Proxy_Node() works in the common case.

Select_Alternates_Proxy_Node(P、F、primary_intf)は、Pへの青いパス(Xを通過)、Pへの赤いパス(Yを通過)、またはprimary_intfからノードF(およびおそらくノードF)は失敗します。基本的なアプローチは、Select_Alternates(X、F、primary_intf)とSelect_Alternates(Y、F、primary_intf)を実行して、Xへの2つのMRTパスとYへの2つのMRTパスのどちらが安全であるかを決定することです。 Fの失敗。一般的に、Fが失敗したときにXまたはYへの特定のパスを使用しても安全で、Select_Proxy_Node_NHs()がそのパスを使用して赤または青のパスを構築してPに到達すると、 Fが失敗したときにPに到達するためにそのパスを使用しても安全です。このルールには、以下で説明する1つの例外があります。まず、一般的なケースでSelect_Alternates_Proxy_Node()がどのように機能するかを具体例で示します。

The 21 ordering relationships used in Select_Proxy_Node_NHs() are repeated in Select_Alternates_Proxy_Node(). We focus on case 4.1.1 to give a detailed example of the reasoning used in Select_Alternates_Proxy_Node(). In Select_Proxy_Node_NHs(), we determined for case 4.1.1 that the red next hops to X and the blue next hops to Y allow us to reach X and Y by disjoint paths, and are thus the blue and red next hops to reach P. Therefore, if Select_Alternates(X, F, primary_intf) is run and we find that it is safe to USE_RED to reach X, then we also conclude that it is safe to use the MRT path through X to reach P (the blue path to P) when F fails. Similarly, if we run Select_Alternates(Y, F, primary_intf) and we find that it is safe to USE_BLUE to reach Y, then we also conclude that it is safe to use the MRT path through Y to reach P (the red path to P) when F fails. If both of the paths that were used in Select_Proxy_Node_NHs() to construct the blue and red paths to P are found to be safe to use to use to reach X and Y, t then we conclude that we can use either the red or the blue path to P.

Select_Proxy_Node_NHs()で使用される21の順序関係は、Select_Alternates_Proxy_Node()でも繰り返されます。 Select_Alternates_Proxy_Node()で使用される推論の詳細な例を示すために、ケース4.1.1に焦点を当てます。 Select_Proxy_Node_NHs()では、ケース4.1.1で、Xへの赤のネクストホップとYへの青のネクストホップにより、互いに素なパスでXとYに到達できるため、Pに到達する青と赤のネクストホップであると判断しました。したがって、Select_Alternates(X、F、primary_intf)が実行され、USE_REDがXに到達しても安全であることがわかった場合、Xを介したMRTパスを使用してP(Pへの青いパス)に到達しても安全であると結論付けます。 )Fが失敗したとき。同様に、Select_Alternates(Y、F、primary_intf)を実行し、USE_BLUEでYに到達しても安全であることがわかった場合は、Yを介したMRTパスを使用してPに到達しても安全であると結論付けます(Pへの赤いパス) )Fが失敗したとき。 Select_Proxy_Node_NHs()でPへの青と赤のパスを作成するために使用されたパスの両方が、XとYに到達するために使用しても安全であることがわかった場合、赤または青のいずれかを使用できると結論付けます。 Pへのパス

This simple reasoning gives the correct answer in most of the cases. However, additional logic is needed when either A or B (but not both A and B) is unordered with respect to S. This applies to cases 4.1.3, 4.2.3, 4.3.1, and 4.3.2. Looking at case 4.1.3 in more detail, A is ordered less than S, but B is unordered with respect to S. In the discussion of case 4.1.3 above, we saw that Select_Proxy_Node_NHs() chose the red path to reach Y and the red path to reach X. We also saw that the red path to reach Y will follow the INCREASING next hops towards the localroot until it reaches some node (L) which is ordered greater than B, after which it will take DECREASING next hops to B. The problem is that the red path to reach P (the one that goes through Y) won't necessarily be the same as the red path to reach Y. This is because the next hop that node L computes for its red next hop to reach P may be different from the next hop it computes for its red next hop to reach Y. This is because B is ordered lower than L, so L applies case 4.1.2 of Select_Proxy_Node_NHs() in order to determine its next hops to reach P. If A.topo_order<B.topo_order (case 4.1.2.1), then L will choose DECREASING next hops directly to B, which is the same result that L computes in Compute_MRT_NextHops() to reach Y. However, if A.topo_order>B.topo_order (case 4.1.2.2), then L will choose INCREASING next hops to reach B, which is different from what L computes in Compute_MRT_NextHops() to reach Y. So, testing the safety of the path for S to reach Y on failure of F as a surrogate for the safety of using the red path to reach P is not reliable in this case. It is possible construct topologies where the red path to P hits F even though the red path to Y does not hit F.

この単純な推論は、ほとんどの場合に正しい答えを与えます。ただし、AまたはB(AとBの両方ではない)のいずれかがSに関して順序付けされていない場合は、追加のロジックが必要です。これは、4.1.3、4.2.3、4.3.1、および4.3.2のケースに適用されます。ケース4.1.3をより詳細に見ると、AはSより少ない順序で並べられていますが、BはSに対して並べられていません。上記のケース4.1.3の説明では、Yに到達するためにSelect_Proxy_Node_NHs()が赤いパスを選択したことがわかりました。 Xに到達するための赤いパス。Yに到達するための赤いパスは、Bより大きく順序付けられたノード(L)に到達するまで、ローカルルートに向かって増加する次のホップをたどり、その後、次のホップに減少するB.問題は、Pに到達するための赤いパス(Yを通過するパス)が必ずしもYに到達するための赤いパスと同じではないことです。これは、ノードLがその赤いネクストホップについて計算するネクストホップが原因です。 Pに到達するためには、Yに到達するための赤いネクストホップについて計算するネクストホップとは異なる場合があります。これは、BがLよりも低い順序になっているため、Lは次のホップを決定するためにSelect_Proxy_Node_NHs()のケース4.1.2を適用しますPに到達します。A.topo_order<B.topo_order(ケース4.1.2.1)の場合、Lは次のホップを直接Bに減少することを選択します。 LがCompute_MRT_NextHops()で計算してYに到達するのと同じ結果。ただし、A.topo_order> B.topo_order(ケース4.1.2.2)の場合、LはINCREASINGネクストホップを選択してBに到達します。これは、LがCompute_MRT_NextHopsで計算するものとは異なります。 ()からYに到達します。したがって、赤のパスを使用してPに到達する安全性の代用として、Fの障害時にSがYに到達するパスの安全性をテストすることは信頼できません。 Yへの赤いパスがFに当たらない場合でも、Pへの赤いパスがFに当たるトポロジを構築することは可能です。

Fortunately, there is enough information in the order relationships that we have already computed to still figure out which alternate to choose in these four cases. The basic idea is to always choose the path involving the ordered node, unless that path would hit F. Returning to case 4.1.3, we see that since A is ordered lower than S, the only way for S to hit F using a simple DECREASING path to A is for F to lie between A and S on the GADAG. This scenario is covered by requiring that F be lower than S (but not also higher than S) and that F.topo_order>A.topo_order in case 4.1.3.1.

幸い、これらの4つのケースでどの代替案を選択するかを判断するために、すでに計算した順序関係には十分な情報があります。基本的な考え方は、順序付けられたノードを含むパスを常に選択することです。ただし、そのパスがFにヒットする場合を除きます。ケース4.1.3に戻ると、AはSよりも低い順序になっているため、SがFにヒットする唯一の方法は、 Aへの減少する経路は、FがGADAG上のAとSの間にあることです。このシナリオは、FがSより低い(ただし、Sよりも高くない)ことと、ケース4.1.3.1のF.topo_order> A.topo_orderが必要であることでカバーされます。

We just need to confirm that it is safe to use the path involving B in this scenario. In case 4.1.3.1, either F is between A and S on the GADAG, or F is unordered with respect to A and lies on the DECREASING path from S to the localroot. When F is between A and S on the GADAG, then the path through B chosen to avoid A in Select_Proxy_Node_NHs() will also avoid F. When F is unordered with respect to A and lies on the DECREASING path from S to the localroot, then we consider two cases. Either F.topo_order<B.topo_order or F.topo_order>B.topo_order. In the first case, since F.topo_order<B.topo_order and F.topo_order>A.topo_order, it must be the case that A.topo_order<B.topo_order. Therefore, L will choose DECREASING next hops directly to B (case 4.1.2.1), which cannot hit F since F.topo_order<B.topo_order. In the second case, where F.topo_order>B.topo_order, the only way for the path involving B to hit F is if it DECREASES from L to B through F, i.e., it must be that L>>F>>B. However, since S>>F, this would imply that S>>B. However, we know that S is unordered with respect to B, so the second case cannot occur. So we have demonstrated that the red path to P (which goes via B and Y) is safe to use under the conditions of 4.1.3.1. Similar reasoning can be applied to the other three special cases where either A or B is unordered with respect to S.

このシナリオでは、Bを含むパスを使用しても安全であることを確認する必要があるだけです。 4.1.3.1の場合、FはGADAG上のAとSの間にあるか、FはAに関して順序付けられておらず、Sからローカルルートへの減少パス上にあります。 FがGADAGのAとSの間にある場合、Select_Proxy_Node_NHs()でAを回避するために選択されたBを通るパスもFを回避します。FがAに関して順序付けられておらず、Sからローカルルートへの減少パスにある場合、 2つのケースを検討します。 F.topo_order <B.topo_orderまたはF.topo_order> B.topo_orderのいずれか。最初のケースでは、F.topo_order <B.topo_orderおよびF.topo_order> A.topo_orderであるため、A.topo_order <B.topo_orderである必要があります。したがって、Lは、Bへのネクストホップを直接減少させることを選択します(ケース4.1.2.1)。F.topo_order<B.topo_orderであるため、Fにヒットすることはできません。 2番目のケースでは、F.topo_order> B.topo_orderの場合、Bを含むパスがFにヒットする唯一の方法は、LからBにFまで減少する場合、つまり、L >> F >> Bである必要があります。ただし、S >> Fなので、これはS >> Bであることを意味します。ただし、SはBに関して順序付けされていないため、2番目のケースは発生しません。したがって、Pへの赤いパス(BおよびYを経由)が4.1.3.1の条件下で安全に使用できることを示しました。同様の推論は、AとBのどちらかがSに関して順序付けられていない他の3つの特殊なケースに適用できます。

6. MRT Lowpoint Algorithm: Next-Hop Conformance
6. MRTローポイントアルゴリズム:ネクストホップ適合

This specification defines the MRT Lowpoint algorithm, which includes the construction of a common GADAG and the computation of MRT-Red and MRT-Blue next hops to each node in the graph. An implementation MAY select any subset of next hops for MRT-Red and MRT-Blue that respect the available nodes that are described in Section 5.7 for each of the MRT-Red and MRT-Blue and the selected next hops are further along in the interval of allowed nodes towards the destination.

この仕様は、一般的なGADAGの構築と、グラフ内の各ノードへのMRT-RedおよびMRT-Blueの次のホップの計算を含むMRT Lowpointアルゴリズムを定義します。実装は、MRT-RedとMRT-Blueのそれぞれについてセクション5.7で説明されている使用可能なノードを尊重するMRT-RedとMRT-Blueのネクストホップのサブセットを選択してもよい(MAY-RedとMRT-Blue)。宛先への許可されたノードの数。

For example, the MRT-Blue next hops used when the destination Y >> X, the computing router, MUST be one or more nodes, T, whose topo_order is in the interval [X.topo_order, Y.topo_order] and where Y >> T or Y is T. Similarly, the MRT-Red next hops MUST be have a topo_order in the interval [R-small.topo_order, X.topo_order] or [Y.topo_order, R-big.topo_order].

たとえば、コンピューティングルーターである宛先Y >> Xの場合に使用されるMRT-Blueネクストホップは、1つ以上のノードTである必要があります。 > TまたはYはTです。同様に、MRT-Redネクストホップは、[R-small.topo_order、X.topo_order]または[Y.topo_order、R-big.topo_order]の間隔でtopo_orderを持つ必要があります。

Implementations SHOULD implement the Select_Alternates() function to pick an MRT-FRR alternate.

実装は、MRT-FRR代替を選択するためにSelect_Alternates()関数を実装する必要があります(SHOULD)。

7. Broadcast Interfaces
7. ブロードキャストインターフェイス

When broadcast interfaces are used to connect nodes, the broadcast network MUST be represented as a pseudonode, where each real node connects to the pseudonode. The interface metric in the direction from real node to pseudonode is the non-zero interface metric, while the interface metric in the direction from the pseudonode to the real node is set to zero. This is consistent with the way that broadcast interfaces are represented as pseudonodes in IS-IS and OSPF.

ブロードキャストインターフェイスを使用してノードを接続する場合、ブロードキャストネットワークは、各実ノードが疑似ノードに接続する疑似ノードとして表す必要があります。実ノードから疑似ノードへの方向のインターフェースメトリックは非ゼロのインターフェースメトリックですが、疑似ノードから実ノードへの方向のインターフェースメトリックはゼロに設定されます。これは、ブロードキャストインターフェイスがIS-ISおよびOSPFで疑似ノードとして表される方法と一致しています。

Pseudonodes MUST be treated as equivalent to real nodes in the network graph used in the MRT Lowpoint algorithm with a few exceptions detailed below.

疑似ノードは、MRTローポイントアルゴリズムで使用されるネットワークグラフの実際のノードと同等として扱われる必要があります。

The pseudonodes MUST be included in the computation of the GADAG. The neighbors of the pseudonode need to know the mrt_node_id of the pseudonode in order to consistently order interfaces, which is needed to compute the GADAG. The mrt_node_id for IS-IS is the 7-octet neighbor system ID and pseudonode number in TLV 22 or TLV 222. The mrt_node_id for OSPFv2 is the 4-octet interface address of the Designated Router found in the Link ID field for the link type 2 (transit network) in the Router-LSA. The mrt_node_id for OSPFv3 is the 4 octet interface address of the Designated Router found in the Neighbor Interface ID field for the link type 2 (transit network) in the Router-LSA. Note that this is different from the Neighbor Router ID field used for the mrt_node_id for point-to-point links in OSPFv3 Router-LSAs given in Figure 15.

疑似ノードは、GADAGの計算に含める必要があります。 GADAGを計算するために必要なインターフェースを一貫して順序付けるには、疑似ノードのネイバーが疑似ノードのmrt_node_idを知っている必要があります。 IS-ISのmrt_node_idは、TLV 22またはTLV 222の7オクテットネイバーシステムIDと疑似ノード番号です。OSPFv2のmrt_node_idは、リンクタイプ2のリンクIDフィールドにある指定ルータの4オクテットインターフェイスアドレスです。 (トランジットネットワーク)ルータLSA内。 OSPFv3のmrt_node_idは、ルーターLSAのリンクタイプ2(トランジットネットワーク)の隣接インターフェースIDフィールドにある指定ルーターの4オクテットインターフェースアドレスです。これは、図15に示したOSPFv3ルーターLSAのポイントツーポイントリンクのmrt_node_idに使用される隣接ルーターIDフィールドとは異なることに注意してください。

Pseudonodes MUST NOT be considered candidates for selection as GADAG root. This rule is intended to result in a more stable network-wide selection of GADAG root by removing the possibility that the change of Designated Router or Designated Intermediate System on a broadcast network can result in a change of GADAG root.

疑似ノードをGADAGルートとして選択する候補と見なしてはなりません。このルールは、ブロードキャストネットワーク上の指定ルーターまたは指定中間システムの変更によりGADAGルートが変更される可能性を排除することにより、GADAGルートのより安定したネットワーク全体の選択をもたらすことを目的としています。

7.1. Computing MRT Next Hops on Broadcast Networks
7.1. ブロードキャストネットワークでのMRTネクストホップの計算

The pseudonode does not correspond to a real node, so it is not actually involved in forwarding. A real node on a broadcast network cannot simply forward traffic to the broadcast network. It must specify another real node on the broadcast network as the next hop. On a network graph where a broadcast network is represented by a pseudonode, this means that if a real node determines that the next hop to reach a given destination is a pseudonode, it must also determine the next-next-hop for that destination in the network graph, which corresponds to a real node attached to the broadcast network.

疑似ノードは実際のノードに対応していないため、実際には転送に関与していません。ブロードキャストネットワーク上の実際のノードは、トラフィックをブロードキャストネットワークに単純に転送することはできません。ブロードキャストネットワーク上の別の実ノードをネクストホップとして指定する必要があります。ブロードキャストネットワークが疑似ノードで表されるネットワークグラフでは、これは、特定の宛先に到達するための次のホップが疑似ノードであると実ノードが判断した場合、そのノードは、その宛先の次の次ホップも決定する必要があることを意味します。ブロードキャストネットワークに接続された実際のノードに対応するネットワークグラフ。

It is interesting to note that this issue is not unique to the MRT algorithm, but is also encountered in normal SPF computations for IGPs. Section 16.1.1 of [RFC2328] describes how this is done for OSPF. When OSPF runs its shortest-path tree calculation, it deals with pseudonodes in the following manner. Whenever the calculating router finds a shorter path to reach a real destination node and the shorter path to the destination is a single pseudonode hop, then the next hop for that destination is taken from the interface IP address in the Router-LSA correspond to the link to the real destination node.

この問題はMRTアルゴリズムに固有のものではなく、IGPの通常のSPF計算でも発生することに注意してください。 [RFC2328]のセクション16.1.1は、OSPFでこれを行う方法を説明しています。 OSPFが最短パスツリー計算を実行する場合、OSPFは次の方法で疑似ノードを処理します。計算ルーターが実際の宛先ノードに到達するためのより短いパスを見つけ、宛先へのより短いパスが単一の疑似ノードホップである場合は常に、その宛先の次のホップは、ルーターに対応するルーターLSAのインターフェイスIPアドレスから取得されます。実際の宛先ノードに。

For IS-IS, in the example pseudocode implementation of Dijkstra's algorithm in Annex C of [ISO10589-Second-Edition], whenever the algorithm encounters an adjacency from a real node to a pseudonode, it gets converted to a set of adjacencies from the real node to the neighbors of the pseudonode. In this way, the computed next hops point all the way to the real node, and not the pseudonode.

IS-ISの場合、[ISO10589-Second-Edition]の付録Cにあるダイクストラのアルゴリズムの疑似コード実装では、アルゴリズムが実際のノードから疑似ノードへの隣接を検出すると、実際の隣接から一連の隣接に変換されます。疑似ノードの隣接ノードへのノード。このようにして、計算されたネクストホップは、疑似ノードではなく実際のノードを指します。

We could avoid the problem of determining next hops across pseudonodes in MRT by converting the pseudonode representation of broadcast networks to a full mesh of links between real nodes on the same network. However, if we make that conversion before computing the GADAG, we lose information about which links actually correspond to a single physical interface into the broadcast network. This could result computing red and blue next hops that use the same broadcast interface, in which case neither the red nor the blue next hop would be usable as an alternate on failure of the broadcast interface.

ブロードキャストネットワークの疑似ノード表現を、同じネットワーク上の実ノード間のリンクのフルメッシュに変換することにより、MRTの疑似ノード間のネクストホップを決定する問題を回避できます。ただし、GADAGを計算する前にその変換を行うと、ブロードキャストネットワークへの単一の物理インターフェイスに実際に対応するリンクに関する情報が失われます。これにより、同じブロードキャストインターフェイスを使用する赤と青のネクストホップが計算される可能性があります。その場合、ブロードキャストインターフェイスの障害時に、赤と青のネクストホップはどちらも代替として使用できません。

Instead, we take the following approach, which maintains the property that either the red and blue next hop will avoid the broadcast network, if topologically allowed. We run the MRT Lowpoint algorithm treating the pseudonodes as equivalent to real nodes in the network graph, with the exceptions noted above. In addition to running the MRT Lowpoint algorithm from the point of view of itself, a computing router connected to a pseudonode MUST also run the MRT Lowpoint algorithm from the point of view of each of its pseudonode neighbors. For example, if a computing router S determines that its MRT red next hop to reach a destination D is a pseudonode P, S looks at its MRT Lowpoint algorithm computation from P's point of view to determine P's red next hop to reach D, say interface 1 on node X. S now knows that its real red next hop to reach D is interface 1 on node X on the broadcast network represented by P, and it can install the corresponding entry in its FIB.

代わりに、トポロジ的に許可されている場合、赤と青のネクストホップのいずれかがブロードキャストネットワークを回避するという特性を維持する次のアプローチを採用します。上記の例外を除き、擬似ノードをネットワークグラフの実際のノードと同等に扱うMRTローポイントアルゴリズムを実行します。自身の観点からMRTローポイントアルゴリズムを実行することに加えて、疑似ノードに接続されたコンピューティングルーターは、その各疑似ノードネイバーの観点からMRTローポイントアルゴリズムも実行する必要があります。たとえば、コンピューティングルータSが、宛先Dに到達するためのMRTレッドネクストホップが疑似ノードPであると判断した場合、Sは、Pの視点からMRTローポイントアルゴリズム計算を調べて、Dに到達するためのPのレッドネクストホップを決定します。ノードXの1。Sは、Dに到達するための実際の赤いネクストホップがPで表されるブロードキャストネットワークのノードXのインターフェイス1であることを認識し、対応するエントリをFIBにインストールできます。

7.2. Using MRT Next Hops as Alternates in the Event of Failures on Broadcast Networks

7.2. ブロードキャストネットワークで障害が発生した場合の代替としてMRTネクストホップを使用する

In the previous section, we specified how to compute MRT next hops when broadcast networks are involved. In this section, we discuss how a PLR can use those MRT next hops in the event of failures involving broadcast networks.

前のセクションでは、ブロードキャストネットワークが関係する場合のMRTネクストホップの計算方法を指定しました。このセクションでは、ブロードキャストネットワークに関連する障害が発生した場合に、PLRがこれらのMRTネクストホップを使用する方法について説明します。

A PLR attached to a broadcast network running only OSPF or IS-IS with large Hello intervals has limited ability to quickly detect failures on a broadcast network. The only failure mode that can be quickly detected is the failure of the physical interface connecting the PLR to the broadcast network. For the failure of the interface connecting the PLR to the broadcast network, the alternate that avoids the broadcast network can be computed by using the broadcast network pseudonode as F, the primary next-hop node, in Select_Alternates(). This will choose an alternate path that avoids the broadcast network. However, the alternate path will not necessarily avoid all of the real nodes connected to the broadcast network. This is because we have used the pseudonode to represent the broadcast network. And we have enforced the node-protecting property of MRT on the pseudonode to provide protection against failure of the broadcast network, not the real next-hop nodes on the broadcast network. This is the best that we can hope to do if failure of the broadcast interface is the only failure mode that the PLR can respond to.

Helloインターバルが大きいOSPFまたはIS-ISのみを実行するブロードキャストネットワークに接続されたPLRは、ブロードキャストネットワークの障害を迅速に検出する機能が制限されています。迅速に検出できる唯一の障害モードは、PLRをブロードキャストネットワークに接続している物理インターフェイスの障害です。 PLRをブロードキャストネットワークに接続するインターフェイスに障害が発生した場合、ブロードキャストネットワークを回避する代替は、Select_Alternates()でプライマリネクストホップノードであるFとしてブロードキャストネットワークの疑似ノードを使用して計算できます。これにより、ブロードキャストネットワークを回避する代替パスが選択されます。ただし、代替パスは、ブロードキャストネットワークに接続されているすべての実ノードを必ずしも回避するわけではありません。これは、ブロードキャストネットワークを表すために疑似ノードを使用したためです。また、ブロードキャストネットワーク上の実際のネクストホップノードではなく、ブロードキャストネットワークの障害に対する保護を提供するために、疑似ノードにMRTのノード保護プロパティを適用しました。これは、ブロードキャストインターフェイスの障害がPLRが応答できる唯一の障害モードである場合に実行できる最善の方法です。

We can improve on this if the PLR also has the ability to quickly detect a lack of connectivity across the broadcast network to a given IP-layer node. This can be accomplished by running BFD between all pairs of IGP neighbors on the broadcast network. Note that in the case of OSPF, this would require establishing BFD sessions between all pairs of neighbors in the 2-WAY state. When the PLR can quickly detect the failure of a particular next hop across a broadcast network, the PLR can be more selective in its choice of alternates. For example, when the PLR observes that connectivity to an IP-layer node on a broadcast network has failed, the PLR may choose to still use the broadcast network to reach other IP-layer nodes that are still reachable. Or, if the PLR observes that connectivity has failed to several IP-layer nodes on the same broadcast network, it may choose to treat the entire broadcast network as failed. The choice of MRT alternates by a PLR for a particular set of failure conditions is a local decision, since it does not require coordination with other nodes.

PLRがブロードキャストネットワークを介して特定のIP層ノードへの接続の欠如をすばやく検出する機能も備えている場合は、これを改善できます。これは、ブロードキャストネットワーク上のIGPネイバーのすべてのペア間でBFDを実行することによって実現できます。 OSPFの場合、これには、2ウェイ状態のネイバーのすべてのペア間でBFDセッションを確立する必要があることに注意してください。 PLRがブロードキャストネットワーク上の特定のネクストホップの障害をすばやく検出できる場合、PLRは代替の選択においてより選択的になります。たとえば、PLRがブロードキャストネットワーク上のIPレイヤーノードへの接続に失敗したことを検出した場合、PLRは、ブロードキャストネットワークを引き続き使用して、まだ到達可能な他のIPレイヤーノードに到達することを選択できます。または、PLRが、同じブロードキャストネットワーク上の複数のIPレイヤーノードへの接続に失敗したことを検出した場合、ブロードキャストネットワーク全体を失敗したものとして扱うことを選択できます。他のノードとの調整を必要としないため、特定の一連の障害状態に対してPLRが代替MRTを選択することはローカルな決定です。

8. Evaluation of Alternative Methods for Constructing GADAGs
8. GADAGを構築するための代替方法の評価

This document specifies the MRT Lowpoint algorithm. One component of the algorithm involves constructing a common GADAG based on the network topology. The MRT Lowpoint algorithm computes the GADAG using the method described in Section 5.5. This method aims to minimize the amount of computation required to compute the GADAG. In the process of developing the MRT Lowpoint algorithm, two alternative methods for constructing GADAGs were also considered. These alternative methods are described in Appendices B and C. In general, these other two methods require more computation to compute the GADAG. The analysis below was performed to determine if the alternative GADAG construction methods produce shorter MRT alternate paths in real network topologies, and if so, to what extent.

このドキュメントでは、MRTローポイントアルゴリズムについて説明します。アルゴリズムの1つのコンポーネントには、ネットワークトポロジに基づいて共通のGADAGを構築することが含まれます。 MRTローポイントアルゴリズムは、セクション5.5で説明されている方法を使用してGADAGを計算します。この方法は、GADAGの計算に必要な計算量を最小限に抑えることを目的としています。 MRTローポイントアルゴリズムの開発プロセスでは、GADAGを作成するための2つの代替方法も検討されました。これらの代替方法については、付録BとCで説明します。一般に、これらの他の2つの方法では、GADAGを計算するためにより多くの計算が必要です。以下の分析は、代替のGADAG構築方法が実際のネットワークトポロジでより短いMRT代替パスを生成するかどうかを決定するために実行されました。

Figure 30 compares results obtained using the three different methods for constructing GADAGs on five different service provider network topologies. MRT_LOWPOINT indicates the method specified in Section 5.5, while MRT_SPF and MRT_HYBRID indicate the methods specified in Appendices B and C, respectively. The columns on the right present the distribution of alternate path lengths for each GADAG construction method. Each MRT computation was performed using a same GADAG root chosen based on centrality.

図30は、5つの異なるサービスプロバイダーネットワークトポロジでGADAGを構築するための3つの異なる方法を使用して得られた結果を比較しています。 MRT_LOWPOINTはセクション5.5で指定されたメソッドを示し、MRT_SPFおよびMRT_HYBRIDはそれぞれ付録BおよびCで指定されたメソッドを示します。右側の列は、各GADAG構築法の代替パスの長さの分布を示しています。各MRT計算は、中心性に基づいて選択された同じGADAGルートを使用して実行されました。

For three of the topologies analyzed (T201, T206, and T211), the use of MRT_SPF or MRT_HYBRID methods does not appear to provide a significantly shorter alternate path lengths compared to the MRT_LOWPOINT method. However, for two of the topologies (T216 and T219), the use of the MRT_SPF method resulted in noticeably shorter alternate path lengths than the use of the MRT_LOWPOINT or MRT_HYBRID methods.

分析した3つのトポロジ(T201、T206、およびT211)では、MRT_SPFまたはMRT_HYBRIDメソッドを使用しても、MRT_LOWPOINTメソッドと比較して大幅に短い代替パス長が得られないようです。ただし、2つのトポロジ(T216およびT219)の場合、MRT_SPFメソッドを使用すると、MRT_LOWPOINTまたはMRT_HYBRIDメソッドを使用する場合よりも代替パスの長さが著しく短くなります。

It was decided to use the MRT_LOWPOINT method to construct the GADAG in the algorithm specified in this document, in order to initially offer an algorithm with lower computational requirements. These results indicate that in the future it may be useful to evaluate and potentially specify other MRT Lowpoint algorithm variants that use different GADAG construction methods.

より低い計算要件のアルゴリズムを最初に提供するために、MRT_LOWPOINTメソッドを使用して、このドキュメントで指定されたアルゴリズムでGADAGを構築することが決定されました。これらの結果は、将来、異なるGADAG構築方法を使用する他のMRT Lowpointアルゴリズムバリアントを評価し、潜在的に指定することが役立つ可能性があることを示しています。

   +-------------------------------------------------------------------+
   |        Topology name         |   percentage of failure scenarios  |
   |                              |  protected by an alternate N hops  |
   |      GADAG construction      |   longer than the primary path     |
   |            method            +------------------------------------+
   |                              |   |   |   |   |   |   |   |   | no |
   |                              |   |   |   |   |   |10 |12 |14 | alt|
   |                              |0-1|2-3|4-5|6-7|8-9|-11|-13|-15| <16|
   +------------------------------+---+---+---+---+---+---+---+---+----+
   |  T201(avg primary hops=3.5)  |   |   |   |   |   |   |   |   |    |
   |  MRT_HYBRID                  | 33| 26| 23|  6|  3|   |   |   |    |
   |  MRT_SPF                     | 33| 36| 23|  6|  3|   |   |   |    |
   |  MRT_LOWPOINT                | 33| 36| 23|  6|  3|   |   |   |    |
   +------------------------------+---+---+---+---+---+---+---+---+----+
   |  T206(avg primary hops=3.7)  |   |   |   |   |   |   |   |   |    |
   |  MRT_HYBRID                  | 50| 35| 13|  2|   |   |   |   |    |
   |  MRT_SPF                     | 50| 35| 13|  2|   |   |   |   |    |
   |  MRT_LOWPOINT                | 55| 32| 13|   |   |   |   |   |    |
   +------------------------------+---+---+---+---+---+---+---+---+----+
   |  T211(avg primary hops=3.3)  |   |   |   |   |   |   |   |   |    |
   |  MRT_HYBRID                  | 86| 14|   |   |   |   |   |   |    |
   |  MRT_SPF                     | 86| 14|   |   |   |   |   |   |    |
   |  MRT_LOWPOINT                | 85| 15|  1|   |   |   |   |   |    |
   +------------------------------+---+---+---+---+---+---+---+---+----+
   |  T216(avg primary hops=5.2)  |   |   |   |   |   |   |   |   |    |
   |  MRT_HYBRID                  | 23| 22| 18| 13| 10|  7|  4|  2|   2|
   |  MRT_SPF                     | 35| 32| 19|  9|  3|  1|   |   |    |
   |  MRT_LOWPOINT                | 28| 25| 18| 11|  7|  6|  3|  2|   1|
   +------------------------------+---+---+---+---+---+---+---+---+----+
   |  T219(avg primary hops=7.7)  |   |   |   |   |   |   |   |   |    |
   |  MRT_HYBRID                  | 20| 16| 13| 10|  7|  5|  5|  5|   3|
   |  MRT_SPF                     | 31| 23| 19| 12|  7|  4|  2|  1|    |
   |  MRT_LOWPOINT                | 19| 14| 15| 12| 10|  8|  7|  6|  10|
   +------------------------------+---+---+---+---+---+---+---+---+----+
        

Figure 30: The Length of Alternate Paths for Various GADAG Construction Methods

図30:さまざまなGADAG構築方法の代替パスの長さ

9. Operational Considerations
9. 運用上の考慮事項

This section discusses operational considerations related to the MRT Lowpoint algorithm and other potential MRT algorithm variants. For a discussion of operational considerations related to MRT-FRR in general, see the "Operational Considerations" section of [RFC7812].

このセクションでは、MRT Lowpointアルゴリズムおよびその他の潜在的なMRTアルゴリズムのバリアントに関連する運用上の考慮事項について説明します。 MRT-FRR全般に関連する運用上の考慮事項については、[RFC7812]の「運用上の考慮事項」セクションを参照してください。

9.1. GADAG Root Selection
9.1. GADAGルート選択

The Default MRT Profile uses the GADAG Root Selection Priority advertised by routers as the primary criterion for selecting the GADAG root. It is RECOMMENDED that an operator designate a set of routers as good choices for selection as GADAG root by setting the GADAG Root Selection Priority for that set of routers to lower (more preferred) numerical values. Criteria for making this designation are discussed below.

デフォルトのMRTプロファイルは、ルータによって通知されたGADAGルート選択優先度を、GADAGルートを選択するための主要な基準として使用します。オペレーターがルーターのセットのGADAGルート選択優先度をより低い(より好ましい)数値に設定することにより、ルーターのセットをGADAGルートとして選択するための適切な選択肢として指定することをお勧めします。この指定を行う基準については、以下で説明します。

Analysis has shown that the centrality of a router can have a significant impact on the lengths of the alternate paths computed. Therefore, it is RECOMMENDED that off-line analysis that considers the centrality of a router be used to help determine how good a choice a particular router is for the role of GADAG root.

分析によると、ルーターの中心性は、計算された代替パスの長さに大きな影響を与える可能性があります。したがって、ルーターの中心性を考慮したオフライン分析を使用して、特定のルーターがGADAGルートの役割にどの程度適しているかを判断するのに役立つことをお勧めします。

If the router currently selected as GADAG root becomes unreachable in the IGP topology, then a new GADAG root will be selected. Changing the GADAG root can change the overall structure of the GADAG as well the paths of the red and MRT-Blue trees built using that GADAG. In order to minimize change in the associated red and MRT-Blue forwarding entries that can result from changing the GADAG root, it is RECOMMENDED that operators prioritize for selection as GADAG root those routers that are expected to consistently remain part of the IGP topology.

現在GADAGルートとして選択されているルーターがIGPトポロジで到達不能になると、新しいGADAGルートが選択されます。 GADAGルートを変更すると、GADAGの全体的な構造だけでなく、そのGADAGを使用して構築された赤およびMRT-Blueツリーのパスも変更されます。 GADAGルートの変更から生じる可能性のある関連する赤およびMRT-Blue転送エントリの変更を最小限に抑えるために、IGPトポロジの一部として一貫して残ることが期待されるルーターをGADAGルートとして選択することをオペレーターが優先することをお勧めします。

9.2. Destination-Rooted GADAGs
9.2. 宛先に根ざしたGADAG

The MRT Lowpoint algorithm constructs a single GADAG rooted at a single node selected as the GADAG root. It is also possible to construct a different GADAG for each destination, with the GADAG rooted at the destination. A router can compute the MRT-Red and MRT-Blue next hops for that destination based on the GADAG rooted at that destination. Building a different GADAG for each destination is computationally more expensive, but it may give somewhat shorter alternate paths. Using destination-rooted GADAGs would require a new MRT profile to be created with a new MRT algorithm specification, since all routers in the MRT Island would need to use destination-rooted GADAGs.

MRTローポイントアルゴリズムは、GADAGルートとして選択された単一のノードをルートとする単一のGADAGを構築します。 GADAGを宛先にルートして、宛先ごとに異なるGADAGを構築することもできます。ルーターは、その宛先をルートとするGADAGに基づいて、その宛先のMRT-RedおよびMRT-Blueネクストホップを計算できます。宛先ごとに異なるGADAGを構築すると、計算コストが高くなりますが、代替パスが多少短くなる場合があります。 MRTアイランド内のすべてのルーターは宛先ルートGADAGを使用する必要があるため、宛先ルートGADAGを使用するには、新しいMRTアルゴリズム仕様で新しいMRTプロファイルを作成する必要があります。

10. Security Considerations
10. セキュリティに関する考慮事項

The algorithm described in this document does not introduce new security concerns beyond those already discussed in the document describing the MRT FRR architecture [RFC7812].

このドキュメントで説明されているアルゴリズムは、MRT FRRアーキテクチャを説明するドキュメント[RFC7812]ですでに説明されているものを超えて、新しいセキュリティの懸念をもたらしません。

11. References
11. 参考文献
11.1. Normative References
11.1. 引用文献

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.

[RFC2119] Bradner、S。、「要件レベルを示すためにRFCで使用するキーワード」、BCP 14、RFC 2119、DOI 10.17487 / RFC2119、1997年3月、<http://www.rfc-editor.org/info/ rfc2119>。

[RFC7812] Atlas, A., Bowers, C., and G. Enyedi, "An Architecture for IP/LDP Fast Reroute Using Maximally Redundant Trees (MRT-FRR)", RFC 7812, DOI 10.17487/RFC7812, June 2016, <http://www.rfc-editor.org/info/rfc7812>.

[RFC7812] Atlas、A.、Bowers、C。、およびG. Enyedi、「最大冗長ツリー(MRT-FRR)を使用したIP / LDP高速リルートのアーキテクチャ」、RFC 7812、DOI 10.17487 / RFC7812、2016年6月、< http://www.rfc-editor.org/info/rfc7812>。

11.2. Informative References
11.2. 参考引用

[EnyediThesis] Enyedi, G., "Novel Algorithms for IP Fast Reroute", Department of Telecommunications and Media Informatics, Budapest University of Technology and Economics Ph.D. Thesis, February 2011, <https://repozitorium.omikk.bme.hu/bitstream/ handle/10890/1040/ertekezes.pdf>.

[EnyediThesis] Enyedi、G。、「IP Fast Rerouteの新しいアルゴリズム」、ブダペスト工科大学経済通信博士、通信・メディア情報学科論文、2011年2月、<https://repozitorium.omikk.bme.hu/bitstream/handle/10890/1040/ertekezes.pdf>。

[IEEE8021Qca] IEEE, "IEEE Standard for Local and metropolitan area networks - Bridges and Bridged Networks - Amendment 24: Path Control and Reservation", IEEE 802.1Qca-2015, DOI 10.1109/IEEESTD.2016.7434544, 2016, <https://standards.ieee.org/findstds/ standard/802.1Qca-2015.html>.

[IEEE8021Qca] IEEE、「IEEE Standard for Local and Metropolitan Area Networks-Bridges and Bridged Networks-Amendment 24:Path Control and Reservation」、IEEE 802.1Qca-2015、DOI 10.1109 / IEEESTD.2016.7434544、2016、<https:// standards .ieee.org / findstds / standard / 802.1Qca-2015.html>。

[ISO10589-Second-Edition] International Organization for Standardization, "Intermediate system to Intermediate system intra-domain routeing information exchange protocol for use in conjunction with the protocol for providing the connectionless-mode Network Service (ISO 8473)", ISO/ IEC 10589:2002, Second Edition, November 2002.

[ISO10589-Second-Edition]国際標準化機構、「コネクションレスモードのネットワークサービス(ISO 8473)を提供するためのプロトコルと組み合わせて使用​​する中間システムから中間システムのドメイン内ルーティング情報交換プロトコル」、ISO / IEC 10589 :2002年、第2版、2002年11月。

[Kahn_1962_topo_sort] Kahn, A., "Topological sorting of large networks", Communications of the ACM, Volume 5, Issue 11 DOI 10.1145/368996.369025, November 1962, <http://dl.acm.org/citation.cfm?doid=368996.369025>.

[Kahn_1962_topo_sort]カーンA.、「大規模ネットワークのトポロジカルソーティング」、Communications of the ACM、Volume 5、Issue 11 DOI 10.1145 / 368996.369025、1962年11月、<http://dl.acm.org/citation.cfm?doid = 368996.369025>。

[MRTLinear] Enyedi, G., Retvari, G., and A. Csaszar, "On Finding Maximally Redundant Trees in Strictly Linear Time", IEEE Symposium on Computers and Communications (ISCC), 2009, <http://opti.tmit.bme.hu/~enyedi/ipfrr/ distMaxRedTree.pdf>.

[MRTLinear] Enyedi、G.、Retvari、G。、およびA. Csaszar、「厳密に線形な時間での最大冗長ツリーの検索について」、IEEEシンポジウムon Computers and Communications(ISCC)、2009、<http://opti.tmit .bme.hu /〜enyedi / ipfrr / distMaxRedTree.pdf>。

[RFC2328] Moy, J., "OSPF Version 2", STD 54, RFC 2328, DOI 10.17487/RFC2328, April 1998, <http://www.rfc-editor.org/info/rfc2328>.

[RFC2328] Moy、J。、「OSPFバージョン2」、STD 54、RFC 2328、DOI 10.17487 / RFC2328、1998年4月、<http://www.rfc-editor.org/info/rfc2328>。

Appendix A. Python Implementation of MRT Lowpoint Algorithm
付録A. MRTローポイントアルゴリズムのPython実装

Below is Python code implementing the MRT Lowpoint algorithm specified in this document. The code is also posted on GitHub <https://github.com/cbowers/draft-ietf-rtgwg-mrt-frr-algorithm/blob/python_code_RFC7811/src/mrt_lowpoint_draft_text.py>.

以下は、このドキュメントで指定されているMRTローポイントアルゴリズムを実装するPythonコードです。コードはGitHub <https://github.com/cbowers/draft-ietf-rtgwg-mrt-frr-algorithm/blob/python_code_RFC7811/src/mrt_lowpoint_draft_text.py>にも投稿されています。

While this Python code is believed to correctly implement the pseudocode description of the algorithm, in the event of a difference, the pseudocode description should be considered normative.

このPythonコードはアルゴリズムの疑似コード記述を正しく実装していると考えられていますが、違いが生じた場合は、疑似コード記述を規範的と見なしてください。

<CODE BEGINS> # This program has been tested to run on Python 2.6 and 2.7 # (specifically Python 2.6.6 and 2.7.8 were tested). # The program has known incompatibilities with Python 3.X.

<CODE BEGINS>#このプログラムは、Python 2.6および2.7での実行がテストされています#(具体的には、Python 2.6.6および2.7.8がテストされています)。 #プログラムはPython 3.Xとの非互換性を認識しています。

# When executed, this program will generate a text file describing # an example topology. It then reads that text file back in as input # to create the example topology, and runs the MRT Lowpoint algorithm. # This was done to simplify the inclusion of the program as a single # text file that can be extracted from the RFC.

#このプログラムを実行すると、トポロジの例を説明したテキストファイルが生成されます。次に、そのテキストファイルを入力として読み込んで#トポロジの例を作成し、MRTローポイントアルゴリズムを実行します。 #これは、プログラムをRFCから抽出できる単一の#テキストファイルとして簡単に含めるために行われました。

# The output of the program is four text files containing a description # of the GADAG, the blue and MRT-Reds for all destinations, and the # MRT alternates for all failures.

#プログラムの出力は、GADAGの説明、すべての宛先の青とMRT-赤、およびすべての障害の#MRT代替案を含む4つのテキストファイルです。

import random import os.path import heapq

ランダムインポートをインポートos.pathインポートヒープ

# simple Class definitions allow structure-like dot notation for
# variables and a convenient place to initialize those variables.
class Topology:
    def __init__(self):
        self.gadag_root = None
        self.node_list = []
        self.node_dict = {}
        self.test_gr = None
        self.island_node_list_for_test_gr = []
        self.stored_named_proxy_dict = {}
        self.init_new_computing_router()
    def init_new_computing_router(self):
        self.island_node_list = []
        self.named_proxy_dict = {}
        
class Node:
    def __init__(self):
        self.node_id = None
        self.intf_list = []
        self.profile_id_list = [0]
        self.GR_sel_priority = 128
        self.blue_next_hops_dict = {}
        self.red_next_hops_dict = {}
        self.blue_to_green_nh_dict = {}
        self.red_to_green_nh_dict = {}
        self.prefix_cost_dict = {}
        self.pnh_dict = {}
        self.alt_dict = {}
        self.init_new_computing_router()
    def init_new_computing_router(self):
        self.island_intf_list = []
        self.IN_MRT_ISLAND = False
        self.IN_GADAG = False
        self.dfs_number = None
        self.dfs_parent = None
        self.dfs_parent_intf = None
        self.dfs_child_list = []
        self.lowpoint_number = None
        self.lowpoint_parent = None
        self.lowpoint_parent_intf = None
        self.localroot = None
        self.block_id = None
        self.IS_CUT_VERTEX = False
        self.blue_next_hops = []
        self.red_next_hops = []
        self.primary_next_hops = []
        self.alt_list = []
        
class Interface:
    def __init__(self):
        self.metric = None
        self.area = None
        self.MRT_INELIGIBLE = False
        self.IGP_EXCLUDED = False
        self.SIMULATION_OUTGOING = False
        self.init_new_computing_router()
    def init_new_computing_router(self):
        self.UNDIRECTED = True
        self.INCOMING = False
        self.OUTGOING = False
        self.INCOMING_STORED = False
        self.OUTGOING_STORED = False
        self.IN_MRT_ISLAND = False
        self.PROCESSED = False
        
class Bundle:
    def __init__(self):
        self.UNDIRECTED = True
        self.OUTGOING = False
        self.INCOMING = False
        
class Alternate:
    def __init__(self):
        self.failed_intf = None
        self.red_or_blue = None
        self.nh_list = []
        self.fec = 'NO_ALTERNATE'
        self.prot = 'NO_PROTECTION'
        self.info = 'NONE'
        
class Proxy_Node_Attachment_Router:
    def __init__(self):
        self.prefix = None
        self.node = None
        self.named_proxy_cost = None
        self.min_lfin = None
        self.nh_intf_list = []
        
class Named_Proxy_Node:
    def __init__(self):
        self.node_id = None  #this is the prefix_id
        self.node_prefix_cost_list = []
        self.lfin_list = []
        self.pnar1 = None
        self.pnar2 = None
        self.pnar_X = None
        self.pnar_Y = None
        self.blue_next_hops = []
        self.red_next_hops = []
        self.primary_next_hops = []
        self.blue_next_hops_dict = {}
        self.red_next_hops_dict = {}
        self.pnh_dict = {}
        self.alt_dict = {}
        

def Interface_Compare(intf_a, intf_b): if intf_a.metric < intf_b.metric: return -1 if intf_b.metric < intf_a.metric: return 1 if intf_a.remote_node.node_id < intf_b.remote_node.node_id:

def Interface_Compare(intf_a、intf_b):if intf_a.metric <intf_b.metric:return -1 if intf_b.metric <intf_a.metric:return 1 if intf_a.remote_node.node_id <intf_b.remote_node.node_id:

return -1 if intf_b.remote_node.node_id < intf_a.remote_node.node_id: return 1 return 0

intf_b.remote_node.node_id <intf_a.remote_node.node_id:if return 1 return 0の場合、-1を返します

def Sort_Interfaces(topo): for node in topo.island_node_list: node.island_intf_list.sort(Interface_Compare)

def Sort_Interfaces(topo):topo.island_node_list:node.island_intf_list.sort(Interface_Compare)のノード用

def Reset_Computed_Node_and_Intf_Values(topo): topo.init_new_computing_router() for node in topo.node_list: node.init_new_computing_router() for intf in node.intf_list: intf.init_new_computing_router()

def Reset_Computed_Node_and_Intf_Values(topo):topo.init_new_computing_router()in node in topo.node_list:node.init_new_computing_router()for intf in node.intf_list:intf.init_new_computing_router()

# This function takes a file with links represented by 2-digit # numbers in the format: # 01,05,10 # 05,02,30 # 02,01,15 # which represents a triangle topology with nodes 01, 05, and 02 # and symmetric metrics of 10, 30, and 15.

#この関数は、次の形式の2桁の番号で表されるリンクを含むファイルを取得します。#01,05,10#05,02,30#02,01,15#ノード01、05、および02#および10、30、15の対称メトリック。

# Inclusion of a fourth column makes the metrics for the link
# asymmetric.  An entry of:
# 02,07,10,15
# creates a link from node 02 to 07 with metrics 10 and 15.
def Create_Topology_From_File(filename):
    topo = Topology()
    node_id_set= set()
    cols_list = []
    # on first pass just create nodes
    with open(filename + '.csv') as topo_file:
        for line in topo_file:
            line = line.rstrip('\r\n')
            cols=line.split(',')
            cols_list.append(cols)
            nodea_node_id = int(cols[0])
            nodeb_node_id = int(cols[1])
            if (nodea_node_id > 999 or nodeb_node_id > 999):
                print("node_id must be between 0 and 999.")
                print("exiting.")
                exit()
            node_id_set.add(nodea_node_id)
            node_id_set.add(nodeb_node_id)
    for node_id in node_id_set:
        node = Node()
        node.node_id = node_id
        topo.node_list.append(node)
        topo.node_dict[node_id] = node
    # on second pass create interfaces
    for cols in cols_list:
        nodea_node_id = int(cols[0])
        nodeb_node_id = int(cols[1])
        metric = int(cols[2])
        reverse_metric = int(cols[2])
        if len(cols) > 3:
            reverse_metric=int(cols[3])
        nodea = topo.node_dict[nodea_node_id]
        nodeb = topo.node_dict[nodeb_node_id]
        nodea_intf = Interface()
        nodea_intf.metric = metric
        nodea_intf.area = 0
        nodeb_intf = Interface()
        nodeb_intf.metric = reverse_metric
        nodeb_intf.area = 0
        nodea_intf.remote_intf = nodeb_intf
        nodeb_intf.remote_intf = nodea_intf
        nodea_intf.remote_node = nodeb
        nodeb_intf.remote_node = nodea
        nodea_intf.local_node = nodea
        nodeb_intf.local_node = nodeb
        nodea_intf.link_data = len(nodea.intf_list)
        nodeb_intf.link_data = len(nodeb.intf_list)
        nodea.intf_list.append(nodea_intf)
        nodeb.intf_list.append(nodeb_intf)
    return topo
        
def MRT_Island_Identification(topo, computing_rtr, profile_id, area):
   if profile_id in computing_rtr.profile_id_list:
       computing_rtr.IN_MRT_ISLAND = True
       explore_list = [computing_rtr]
   else:
       return
   while explore_list != []:
       next_rtr = explore_list.pop()
       for intf in next_rtr.intf_list:
           if ( (not intf.IN_MRT_ISLAND)
                and (not intf.MRT_INELIGIBLE)
                and (not intf.remote_intf.MRT_INELIGIBLE)
                and (not intf.IGP_EXCLUDED) and intf.area == area
                and (profile_id in intf.remote_node.profile_id_list)):
                intf.IN_MRT_ISLAND = True
                intf.remote_intf.IN_MRT_ISLAND = True
                if (not intf.remote_node.IN_MRT_ISLAND):
        

intf.remote_INTF.IN_MRT_ISLAND = True explore_list.append(intf.remote_node)

intf.remote_INTF.IN_MRT_ISLAND = True explore_list.append(intf.remote_node)

def Compute_Island_Node_List_For_Test_GR(topo, test_gr): Reset_Computed_Node_and_Intf_Values(topo) topo.test_gr = topo.node_dict[test_gr] MRT_Island_Identification(topo, topo.test_gr, 0, 0) for node in topo.node_list: if node.IN_MRT_ISLAND: topo.island_node_list_for_test_gr.append(node)

def Compute_Island_Node_List_For_Test_GR(topo、test_gr):Reset_Computed_Node_and_Intf_Values(topo)topo.test_gr = topo.node_dict [test_gr] MRT_Island_Identification(topo、topo.test_gr、0、0)for topo.node_in_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list_to_is_list append(node)

def Set_Island_Intf_and_Node_Lists(topo): for node in topo.node_list: if node.IN_MRT_ISLAND: topo.island_node_list.append(node) for intf in node.intf_list: if intf.IN_MRT_ISLAND: node.island_intf_list.append(intf)

def Set_Island_Intf_and_Node_Lists(topo):for node in topo.node_list:if node.IN_MRT_ISLAND:topo.island_node_list.append(node)for intf in node.intf_list:if intf.IN_MRT_ISLAND:node.island_intf_list.append

global_dfs_number = None
        
def Lowpoint_Visit(x, parent, intf_p_to_x):
    global global_dfs_number
    x.dfs_number = global_dfs_number
    x.lowpoint_number = x.dfs_number
    global_dfs_number += 1
    x.dfs_parent = parent
    if intf_p_to_x == None:
        x.dfs_parent_intf = None
    else:
        x.dfs_parent_intf = intf_p_to_x.remote_intf
    x.lowpoint_parent = None
    if parent != None:
        parent.dfs_child_list.append(x)
    for intf in x.island_intf_list:
        if intf.remote_node.dfs_number == None:
            Lowpoint_Visit(intf.remote_node, x, intf)
            if intf.remote_node.lowpoint_number < x.lowpoint_number:
                x.lowpoint_number = intf.remote_node.lowpoint_number
                x.lowpoint_parent = intf.remote_node
                x.lowpoint_parent_intf = intf
        else:
            if intf.remote_node is not parent:
                if intf.remote_node.dfs_number < x.lowpoint_number:
                    x.lowpoint_number = intf.remote_node.dfs_number
                    x.lowpoint_parent = intf.remote_node
                    x.lowpoint_parent_intf = intf
        

def Run_Lowpoint(topo): global global_dfs_number global_dfs_number = 0 Lowpoint_Visit(topo.gadag_root, None, None)

def Run_Lowpoint(topo):global global_dfs_number global_dfs_number = 0 Lowpoint_Visit(topo.gadag_root、None、None)

max_block_id = None
        

def Assign_Block_ID(x, cur_block_id): global max_block_id x.block_id = cur_block_id for c in x.dfs_child_list: if (c.localroot is x): max_block_id += 1 Assign_Block_ID(c, max_block_id) else: Assign_Block_ID(c, cur_block_id)

def Assign_Block_ID(x、cur_block_id):global max_block_id x.block_id = cur_block_id in c in x.dfs_child_list:if(c.localroot is x):max_block_id + = 1 Assign_Block_ID(c、max_block_id)else:Assign_Block_ID(c、cur_block_id)

def Run_Assign_Block_ID(topo): global max_block_id max_block_id = 0 Assign_Block_ID(topo.gadag_root, max_block_id)

def Run_Assign_Block_ID(topo):global max_block_id max_block_id = 0 Assign_Block_ID(topo.gadag_root、max_block_id)

def Construct_Ear(x, stack, intf, ear_type):
    ear_list = []
    cur_intf = intf
    not_done = True
    while not_done:
        cur_intf.UNDIRECTED = False
        cur_intf.OUTGOING = True
        cur_intf.remote_intf.UNDIRECTED = False
        cur_intf.remote_intf.INCOMING = True
        if cur_intf.remote_node.IN_GADAG == False:
            cur_intf.remote_node.IN_GADAG = True
            ear_list.append(cur_intf.remote_node)
            if ear_type == 'CHILD':
                cur_intf = cur_intf.remote_node.lowpoint_parent_intf
            else:
                assert ear_type == 'NEIGHBOR'
                cur_intf = cur_intf.remote_node.dfs_parent_intf
        else:
            not_done = False
        

if ear_type == 'CHILD' and cur_intf.remote_node is x: # x is a cut-vertex and the local root for the block # in which the ear is computed x.IS_CUT_VERTEX = True localroot = x else:

ear_type == 'CHILD'でcur_intf.remote_nodeがxの場合:#xはカット頂点であり、耳が計算されるブロックのローカルルート##IS_CUT_VERTEX = True localroot = x else:

# inherit local root from the end of the ear localroot = cur_intf.remote_node.localroot

#耳の端からローカルルートを継承しますlocalroot = cur_intf.remote_node.localroot

    while ear_list != []:
        y = ear_list.pop()
        y.localroot = localroot
        stack.append(y)
        
def Construct_GADAG_via_Lowpoint(topo):
    gadag_root = topo.gadag_root
    gadag_root.IN_GADAG = True
    gadag_root.localroot = None
    stack = []
    stack.append(gadag_root)
    while stack != []:
        x = stack.pop()
        for intf in x.island_intf_list:
            if ( intf.remote_node.IN_GADAG == False
                 and intf.remote_node.dfs_parent is x ):
                Construct_Ear(x, stack, intf, 'CHILD' )
        for intf in x.island_intf_list:
            if (intf.remote_node.IN_GADAG == False
                and intf.remote_node.dfs_parent is not x):
                Construct_Ear(x, stack, intf, 'NEIGHBOR')
        
def Assign_Remaining_Lowpoint_Parents(topo):
    for node in topo.island_node_list:
        if ( node is not topo.gadag_root
            and node.lowpoint_parent == None ):
            node.lowpoint_parent = node.dfs_parent
            node.lowpoint_parent_intf = node.dfs_parent_intf
            node.lowpoint_number = node.dfs_parent.dfs_number
        
def Add_Undirected_Block_Root_Links(topo):
    for node in topo.island_node_list:
        if node.IS_CUT_VERTEX or node is topo.gadag_root:
            for intf in node.island_intf_list:
                if ( intf.remote_node.localroot is not node
                     or intf.PROCESSED ):
                    continue
                bundle_list = []
                bundle = Bundle()
                for intf2 in node.island_intf_list:
                    if intf2.remote_node is intf.remote_node:
                        bundle_list.append(intf2)
                        if not intf2.UNDIRECTED:
                            bundle.UNDIRECTED = False
                            if intf2.INCOMING:
        

bundle.INCOMING = True if intf2.OUTGOING: bundle.OUTGOING = True if bundle.UNDIRECTED: for intf3 in bundle_list: intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intf3.PROCESSED = True intf3.remote_intf.PROCESSED = True intf3.OUTGOING = True intf3.remote_intf.INCOMING = True else: if (bundle.OUTGOING and bundle.INCOMING): for intf3 in bundle_list: intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intf3.PROCESSED = True intf3.remote_intf.PROCESSED = True intf3.OUTGOING = True intf3.INCOMING = True intf3.remote_intf.INCOMING = True intf3.remote_intf.OUTGOING = True elif bundle.OUTGOING: for intf3 in bundle_list: intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intf3.PROCESSED = True intf3.remote_intf.PROCESSED = True intf3.OUTGOING = True intf3.remote_intf.INCOMING = True elif bundle.INCOMING: for intf3 in bundle_list: intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intf3.PROCESSED = True intf3.remote_intf.PROCESSED = True intf3.INCOMING = True intf3.remote_intf.OUTGOING = True

bundle.INCOMING = true intf2.OUTGOINGの場合:bundle.OUTGOING = true bundle.UNDIRECTEDの場合:bundle_listのintf3の場合:intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intf3.PROCESSED = True intf3.remote_intf.PROfESSED = True .OUTGOING = True intf3.remote_intf.INCOMING = True else:if(bundle.OUTGOING and bundle.INCOMING):for bundle_list:intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intf3.PROCESSED = True intf3.remote_int PROCESSED = True intf3.OUTGOING = True intf3.INCOMING = True intf3.remote_intf.INCOMING = True intf3.remote_intf.OUTGOING = True elif bundle.OUTGOING:for intf3 in bundle_list:intf3.UNDIRECTED = False intf3.remoteED.intfUNINTEDFUN .PROCESSED = True intf3.remote_intf.PROCESSED = True intf3.OUTGOING = True intf3.remote_intf.INCOMING = True elif bundle.INCOMING:for bundle_list:intf3.UNDIRECTED = False intf3.remote_intf.UNDIRECTED = False intfINTFED intf3.remote_intf.PROCESSED = True intf3.INCOMIN G = True intf3.remote_intf.OUTGOING = True

def Modify_Block_Root_Incoming_Links(topo):
    for node in topo.island_node_list:
        if ( node.IS_CUT_VERTEX == True or node is topo.gadag_root ):
            for intf in node.island_intf_list:
                if intf.remote_node.localroot is node:
                    if intf.INCOMING:
                        intf.INCOMING = False
                        intf.INCOMING_STORED = True
                        intf.remote_intf.OUTGOING = False
                        intf.remote_intf.OUTGOING_STORED = True
        
def Revert_Block_Root_Incoming_Links(topo):
    for node in topo.island_node_list:
        if ( node.IS_CUT_VERTEX == True or node is topo.gadag_root ):
            for intf in node.island_intf_list:
                if intf.remote_node.localroot is node:
                    if intf.INCOMING_STORED:
                        intf.INCOMING = True
                        intf.remote_intf.OUTGOING = True
                        intf.INCOMING_STORED = False
                        intf.remote_intf.OUTGOING_STORED = False
        
def Run_Topological_Sort_GADAG(topo):
    Modify_Block_Root_Incoming_Links(topo)
    for node in topo.island_node_list:
        node.unvisited = 0
        for intf in node.island_intf_list:
            if (intf.INCOMING == True):
                node.unvisited += 1
    working_list = []
    topo_order_list = []
    working_list.append(topo.gadag_root)
    while working_list != []:
        y = working_list.pop(0)
        topo_order_list.append(y)
        for intf in y.island_intf_list:
            if ( intf.OUTGOING == True):
                intf.remote_node.unvisited -= 1
                if intf.remote_node.unvisited == 0:
                    working_list.append(intf.remote_node)
    next_topo_order = 1
    while topo_order_list != []:
        y = topo_order_list.pop(0)
        y.topo_order = next_topo_order
        next_topo_order += 1
    Revert_Block_Root_Incoming_Links(topo)
        

def Set_Other_Undirected_Links_Based_On_Topo_Order(topo): for node in topo.island_node_list: for intf in node.island_intf_list: if intf.UNDIRECTED: if node.topo_order < intf.remote_node.topo_order: intf.OUTGOING = True intf.UNDIRECTED = False intf.remote_intf.INCOMING = True intf.remote_intf.UNDIRECTED = False else:

def Set_Other_Undirected_Links_Based_On_Topo_Order(topo):for node in topo.island_node_list:for intf in node.island_intf_list:if intf.UNDIRECTED:if node.topo_order <intf.remote_node.topo_order:intf.OUTGOt = Inff.OUTGOt = True intfint_fremintfint_frem_intremote.Fint INCOMING = True intf.remote_intf.UNDIRECTED = Falseその他:

intf.INCOMING = True intf.UNDIRECTED = False intf.remote_intf.OUTGOING = True intf.remote_intf.UNDIRECTED = False

intf.INCOMING = True intf.UNDIRECTED = False intf.remote_intf.OUTGOING = True intf.remote_intf.UNDIRECTED = False

def Initialize_Temporary_Interface_Flags(topo): for node in topo.island_node_list: for intf in node.island_intf_list: intf.PROCESSED = False intf.INCOMING_STORED = False intf.OUTGOING_STORED = False

def Initialize_Temporary_Interface_Flags(topo):forpo.island_node_list:for intf in node.island_intf_list:intf.PROCESSED = False intf.INCOMING_STORED = False intf.OUTGOING_STORED = False

def Add_Undirected_Links(topo): Initialize_Temporary_Interface_Flags(topo) Add_Undirected_Block_Root_Links(topo) Run_Topological_Sort_GADAG(topo) Set_Other_Undirected_Links_Based_On_Topo_Order(topo)

def Add_Undirected_Links(topo):Initialize_Temporary_Interface_Flags(topo)Add_Undirected_Block_Root_Links(topo)Run_Topological_Sort_GADAG(topo)Set_Other_Undirected_Links_Based_On_Topo_Order(topo)

def In_Common_Block(x,y): if ( (x.block_id == y.block_id) or ( x is y.localroot) or (y is x.localroot) ): return True return False

def In_Common_Block(x、y):if(((x.block_id == y.block_id)or(x is y.localroot)または(y is x.localroot)):return True return False

def Copy_List_Items(target_list, source_list):
    del target_list[:] # Python idiom to remove all elements of a list
    for element in source_list:
        target_list.append(element)
        

def Add_Item_To_List_If_New(target_list, item): if item not in target_list: target_list.append(item)

def Add_Item_To_List_If_New(target_list、item):item item not target_list:target_list.append(item)

def Store_Results(y, direction):
    if direction == 'INCREASING':
        y.HIGHER = True
        Copy_List_Items(y.blue_next_hops, y.next_hops)
    if direction == 'DECREASING':
        y.LOWER = True
        Copy_List_Items(y.red_next_hops, y.next_hops)
    if direction == 'NORMAL_SPF':
        y.primary_spf_metric = y.spf_metric
        Copy_List_Items(y.primary_next_hops, y.next_hops)
    if direction == 'MRT_ISLAND_SPF':
        Copy_List_Items(y.mrt_island_next_hops, y.next_hops)
    if direction == 'COLLAPSED_SPF':
        y.collapsed_metric = y.spf_metric
        Copy_List_Items(y.collapsed_next_hops, y.next_hops)
        
# Note that the Python heapq function allows for duplicate items,
# so we use the 'spf_visited' property to only consider a node
# as min_node the first time it gets removed from the heap.
def SPF_No_Traverse_Block_Root(topo, spf_root, block_root, direction):
    spf_heap = []
    for y in topo.island_node_list:
        y.spf_metric = 2147483647 # 2^31-1
        y.next_hops = []
        y.spf_visited = False
    spf_root.spf_metric = 0
    heapq.heappush(spf_heap,
                   (spf_root.spf_metric, spf_root.node_id,  spf_root) )
    while spf_heap != []:
        #extract third element of tuple popped from heap
        min_node = heapq.heappop(spf_heap)[2]
        if min_node.spf_visited:
            continue
        min_node.spf_visited = True
        Store_Results(min_node, direction)
        if ( (min_node is spf_root) or (min_node is not block_root) ):
            for intf in min_node.island_intf_list:
                if ( ( (direction == 'INCREASING' and intf.OUTGOING )
                    or (direction == 'DECREASING' and intf.INCOMING ) )
                    and In_Common_Block(spf_root, intf.remote_node) ) :
                    path_metric = min_node.spf_metric + intf.metric
                    if path_metric < intf.remote_node.spf_metric:
                        intf.remote_node.spf_metric = path_metric
                        if min_node is spf_root:
                            intf.remote_node.next_hops = [intf]
                        else:
                            Copy_List_Items(intf.remote_node.next_hops,
                                            min_node.next_hops)
                        heapq.heappush(spf_heap,
                                       ( intf.remote_node.spf_metric,
                                         intf.remote_node.node_id,
                                         intf.remote_node ) )
                    elif path_metric == intf.remote_node.spf_metric:
                        if min_node is spf_root:
                            Add_Item_To_List_If_New(
                                intf.remote_node.next_hops,intf)
                        else:
                            for nh_intf in min_node.next_hops:
                                Add_Item_To_List_If_New(
                                    intf.remote_node.next_hops,nh_intf)
        
def Normal_SPF(topo, spf_root):
    spf_heap = []
    for y in topo.node_list:
        
        y.spf_metric = 2147483647 # 2^31-1 as max metric
        y.next_hops = []
        y.primary_spf_metric = 2147483647
        y.primary_next_hops = []
        y.spf_visited = False
    spf_root.spf_metric = 0
    heapq.heappush(spf_heap,
                   (spf_root.spf_metric,spf_root.node_id,spf_root) )
    while spf_heap != []:
        #extract third element of tuple popped from heap
        min_node = heapq.heappop(spf_heap)[2]
        if min_node.spf_visited:
            continue
        min_node.spf_visited = True
        Store_Results(min_node, 'NORMAL_SPF')
        for intf in min_node.intf_list:
            path_metric = min_node.spf_metric + intf.metric
            if path_metric < intf.remote_node.spf_metric:
                intf.remote_node.spf_metric = path_metric
                if min_node is spf_root:
                    intf.remote_node.next_hops = [intf]
                else:
                    Copy_List_Items(intf.remote_node.next_hops,
                                    min_node.next_hops)
                heapq.heappush(spf_heap,
                               ( intf.remote_node.spf_metric,
                                 intf.remote_node.node_id,
                                 intf.remote_node ) )
            elif path_metric == intf.remote_node.spf_metric:
                if min_node is spf_root:
                    Add_Item_To_List_If_New(
                        intf.remote_node.next_hops,intf)
                else:
                    for nh_intf in min_node.next_hops:
                        Add_Item_To_List_If_New(
                            intf.remote_node.next_hops,nh_intf)
        
def Set_Edge(y):
    if (y.blue_next_hops == [] and y.red_next_hops == []):
        Set_Edge(y.localroot)
        Copy_List_Items(y.blue_next_hops,y.localroot.blue_next_hops)
        Copy_List_Items(y.red_next_hops ,y.localroot.red_next_hops)
        y.order_proxy = y.localroot.order_proxy
        
def Compute_MRT_NH_For_One_Src_To_Island_Dests(topo,x):
    for y in topo.island_node_list:
        y.HIGHER = False
        y.LOWER = False
        y.red_next_hops = []
        y.blue_next_hops = []
        y.order_proxy = y
    SPF_No_Traverse_Block_Root(topo, x, x.localroot, 'INCREASING')
    SPF_No_Traverse_Block_Root(topo, x, x.localroot, 'DECREASING')
    for y in topo.island_node_list:
        if ( y is not x and (y.block_id == x.block_id) ):
            assert (not ( y is x.localroot or x is y.localroot) )
            assert(not (y.HIGHER and y.LOWER) )
            if y.HIGHER == True:
                Copy_List_Items(y.red_next_hops,
                                x.localroot.red_next_hops)
            elif y.LOWER == True:
                Copy_List_Items(y.blue_next_hops,
                                x.localroot.blue_next_hops)
            else:
                Copy_List_Items(y.blue_next_hops,
                                x.localroot.red_next_hops)
                Copy_List_Items(y.red_next_hops,
                                x.localroot.blue_next_hops)
        

# Inherit x's MRT next hops to reach the GADAG root # from x's MRT next hops to reach its local root, # but first check if x is the gadag_root (in which case # x does not have a local root) or if x's local root # is the gadag root (in which case we already have the # x's MRT next hops to reach the gadag root) if x is not topo.gadag_root and x.localroot is not topo.gadag_root: Copy_List_Items(topo.gadag_root.blue_next_hops, x.localroot.blue_next_hops) Copy_List_Items(topo.gadag_root.red_next_hops, x.localroot.red_next_hops) topo.gadag_root.order_proxy = x.localroot

#xのMRTネクストホップを継承してGADAGルートに到達する#xのMRTネクストホップからローカルルートに到達する#最初にxがgadag_root(この場合、xにはローカルルートがない)かどうか、またはxのローカルルートかどうかをチェックするxがtopo.gadag_rootでなく、x.localrootがtopo.gadag_rootでない場合、#はgadagルートです(この場合、#xのMRTネクストホップはすでにあります):Copy_List_Items(topo.gadag_root.blue_next_hops、x .localroot.blue_next_hops)Copy_List_Items(topo.gadag_root.red_next_hops、x.localroot.red_next_hops)topo.gadag_root.order_proxy = x.localroot

# Inherit next hops and order_proxies to other blocks for y in topo.island_node_list: if (y is not topo.gadag_root and y is not x ): Set_Edge(y)

#topo.island_node_listでyのネクストホップとorder_proxiesを他のブロックに継承:if(yがtopo.gadag_rootでなく、yがxではない):Set_Edge(y)

def Store_MRT_Nexthops_For_One_Src_To_Island_Dests(topo,x):
    for y in topo.island_node_list:
        if y is x:
            continue
        x.blue_next_hops_dict[y.node_id] = []
        x.red_next_hops_dict[y.node_id] = []
        Copy_List_Items(x.blue_next_hops_dict[y.node_id],
                        y.blue_next_hops)
        

Copy_List_Items(x.red_next_hops_dict[y.node_id], y.red_next_hops)

Copy_List_Items(x.red_next_hops_dict [y.node_id]、y.red_next_hops)

def Store_Primary_and_Alts_For_One_Src_To_Island_Dests(topo,x):
    for y in topo.island_node_list:
        x.pnh_dict[y.node_id] = []
        Copy_List_Items(x.pnh_dict[y.node_id], y.primary_next_hops)
        x.alt_dict[y.node_id] = []
        Copy_List_Items(x.alt_dict[y.node_id], y.alt_list)
        
def Store_Primary_NHs_For_One_Source_To_Nodes(topo,x):
    for y in topo.node_list:
        x.pnh_dict[y.node_id] = []
        Copy_List_Items(x.pnh_dict[y.node_id], y.primary_next_hops)
        
def Store_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,x):
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        x.blue_next_hops_dict[P.node_id] = []
        x.red_next_hops_dict[P.node_id] = []
        Copy_List_Items(x.blue_next_hops_dict[P.node_id],
                        P.blue_next_hops)
        Copy_List_Items(x.red_next_hops_dict[P.node_id],
                        P.red_next_hops)
        
def Store_Alts_For_One_Src_To_Named_Proxy_Nodes(topo,x):
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        x.alt_dict[P.node_id] = []
        Copy_List_Items(x.alt_dict[P.node_id],
                        P.alt_list)
        
def Store_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,x):
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        x.pnh_dict[P.node_id] = []
        Copy_List_Items(x.pnh_dict[P.node_id],
                        P.primary_next_hops)
        

def Select_Alternates_Internal(D, F, primary_intf, D_lower, D_higher, D_topo_order): if D_higher and D_lower: if F.HIGHER and F.LOWER: if F.topo_order > D_topo_order: return 'USE_BLUE' else: return 'USE_RED' if F.HIGHER:

def Select_Alternates_Internal(D、F、primary_intf、D_lower、D_higher、D_topo_order):if D_higher and D_lower:if F.HIGHER and F.LOWER:if F.topo_order> D_topo_order:return 'USE_BLUE' else:return 'USE_RED' if F.より高い:

return 'USE_RED' if F.LOWER: return 'USE_BLUE' assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_INELIGIBLE) return 'USE_RED_OR_BLUE' if D_higher: if F.HIGHER and F.LOWER: return 'USE_BLUE' if F.LOWER: return 'USE_BLUE' if F.HIGHER: if (F.topo_order > D_topo_order): return 'USE_BLUE' if (F.topo_order < D_topo_order): return 'USE_RED' assert(False) assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_INELIGIBLE) return 'USE_RED_OR_BLUE' if D_lower: if F.HIGHER and F.LOWER: return 'USE_RED' if F.HIGHER: return 'USE_RED' if F.LOWER: if F.topo_order > D_topo_order: return 'USE_BLUE' if F.topo_order < D_topo_order: return 'USE_RED' assert(False) assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_INELIGIBLE) return 'USE_RED_OR_BLUE' else: # D is unordered wrt S if F.HIGHER and F.LOWER: if primary_intf.OUTGOING and primary_intf.INCOMING: # This can happen when F and D are in different blocks return 'USE_RED_OR_BLUE' if primary_intf.OUTGOING: return 'USE_BLUE' if primary_intf.INCOMING: return 'USE_RED' #This can occur when primary_intf is MRT_INELIGIBLE. #This appears to be a case where the special #construction of the GADAG allows us to choose red, #whereas with an arbitrary GADAG, neither red nor blue #is guaranteed to work.

F.LOWERの場合は「USE_RED」を返します。assert(primary_intf.MRT_INELIGIBLEまたはprimary_intf.remote_intf.MRT_INELIGIBLE)を返します。D_higherの場合は「USE_RED_OR_BLUE」を返します。F.HIGHERの場合はF.LOWER:F.LOWERの場合は「USE_BLUE」を返します。 F.HIGHERの場合は 'USE_BLUE'を返す:if(F.topo_order> D_topo_order):return 'USE_BLUE' if(F.topo_order <D_topo_order):return 'USE_RED' assert(False)assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_MINT_LIFBLE )D_lowerの場合は「USE_RED_OR_BLUE」を返し、F.HIGHERの場合はF.LOWERを返します。F.HIGHERの場合は「USE_RED」を返します。F.LOWERの場合は「USE_RED」を返します。 <D_topo_order:return 'USE_RED' assert(False)assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_INELIGIBLE)return 'USE_RED_OR_BLUE' else:#Dは、F.HIGHERとF.LOWERの場合、Sに対して順序付けされていません。primary_intf_OUTGOINGの場合.INCOMING:#これは、primary_intf.OUTGOING:retuの場合、FとDが異なるブロックにあるときに 'USE_RED_OR_BLUE'を返すときに発生する可能性があります。 rn 'USE_BLUE' if primary_intf.INCOMING:return 'USE_RED'#これは、primary_intfがMRT_INELIGIBLEの場合に発生する可能性があります。 #これは、GADAGの特別な#構築により赤を選択できる場合のようですが、任意のGADAGでは#赤も青も動作することが保証されていません。

assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_INELIGIBLE) return 'USE_RED' if F.LOWER: return 'USE_RED' if F.HIGHER: return 'USE_BLUE' assert(primary_intf.MRT_INELIGIBLE or primary_intf.remote_intf.MRT_INELIGIBLE) if F.topo_order > D_topo_order: return 'USE_BLUE' else: return 'USE_RED'

assert(primary_intf.MRT_INELIGIBLEまたはprimary_intf.remote_intf.MRT_INELIGIBLE)F.LOWERの場合は「USE_RED」を返します:F.HIGHERの場合は「USE_RED」を返します:「USE_BLUE」を返します> D_topo_order: 'USE_BLUE'を返すelse: 'USE_RED'を返す

def Select_Alternates(D, F, primary_intf): S = primary_intf.local_node if not In_Common_Block(F, S): return 'PRIM_NH_IN_DIFFERENT_BLOCK' if (D is F) or (D.order_proxy is F): return 'PRIM_NH_IS_D_OR_OP_FOR_D' D_lower = D.order_proxy.LOWER D_higher = D.order_proxy.HIGHER D_topo_order = D.order_proxy.topo_order return Select_Alternates_Internal(D, F, primary_intf, D_lower, D_higher, D_topo_order)

def Select_Alternates(D、F、primary_intf):S = primary_intf.local_node not if if In_Common_Block(F、S):return 'PRIM_NH_IN_DIFFERENT_BLOCK' if(D is F)or(D.order_proxy is F):return 'PRIM_NH_IS_D_OR_OP_lowerD' .order_proxy.LOWER D_higher = D.order_proxy.HIGHER D_topo_order = D.order_proxy.topo_order return Select_Alternates_Internal(D、F、primary_intf、D_lower、D_higher、D_topo_order)

def Is_Remote_Node_In_NH_List(node, intf_list): for intf in intf_list: if node is intf.remote_node: return True return False

def Is_Remote_Node_In_NH_List(node、intf_list):for intf in intf_list:if node is intf.remote_node:return True return False

def Select_Alts_For_One_Src_To_Island_Dests(topo,x):
    Normal_SPF(topo, x)
    for D in topo.island_node_list:
        D.alt_list = []
        if D is x:
            continue
        for failed_intf in D.primary_next_hops:
            alt = Alternate()
            alt.failed_intf = failed_intf
            cand_alt_list = []
            F = failed_intf.remote_node
            #We need to test if F is in the island, as opposed
            #to just testing if failed_intf is in island_intf_list,
            #because failed_intf could be marked as MRT_INELIGIBLE.
            if F in topo.island_node_list:
        

alt.info = Select_Alternates(D, F, failed_intf) else: #The primary next hop is not in the MRT Island. #Either red or blue will avoid the primary next hop, #because the primary next hop is not even in the #GADAG. alt.info = 'USE_RED_OR_BLUE'

alt.info = Select_Alternates(D、F、failed_intf)else:#プライマリネクストホップはMRTアイランドにありません。 #赤または青のどちらかがプライマリネクストホップを回避します。#プライマリネクストホップが#GADAGにないためです。 alt.info = 'USE_RED_OR_BLUE'

            if (alt.info == 'USE_RED_OR_BLUE'):
                alt.red_or_blue = random.choice(['USE_RED','USE_BLUE'])
            if (alt.info == 'USE_BLUE'
                or alt.red_or_blue == 'USE_BLUE'):
                Copy_List_Items(alt.nh_list, D.blue_next_hops)
                alt.fec = 'BLUE'
                alt.prot = 'NODE_PROTECTION'
            if (alt.info == 'USE_RED' or alt.red_or_blue == 'USE_RED'):
                Copy_List_Items(alt.nh_list, D.red_next_hops)
                alt.fec = 'RED'
                alt.prot = 'NODE_PROTECTION'
            if (alt.info == 'PRIM_NH_IN_DIFFERENT_BLOCK'):
                alt.fec = 'NO_ALTERNATE'
                alt.prot = 'NO_PROTECTION'
            if (alt.info == 'PRIM_NH_IS_D_OR_OP_FOR_D'):
                if failed_intf.OUTGOING and failed_intf.INCOMING:
                    # cut-link: if there are parallel cut links, use
                    # the link(s) with lowest metric that are not
                    # primary intf or None
                    cand_alt_list = [None]
                    min_metric = 2147483647
                    for intf in x.island_intf_list:
                        if ( intf is not failed_intf and
                             (intf.remote_node is
                             failed_intf.remote_node)):
                            if intf.metric < min_metric:
                                cand_alt_list = [intf]
                                min_metric = intf.metric
                            elif intf.metric == min_metric:
                                cand_alt_list.append(intf)
                    if cand_alt_list != [None]:
                        alt.fec = 'GREEN'
                        alt.prot = 'PARALLEL_CUTLINK'
                    else:
                        alt.fec = 'NO_ALTERNATE'
                        alt.prot = 'NO_PROTECTION'
                    Copy_List_Items(alt.nh_list, cand_alt_list)
        

# Is_Remote_Node_In_NH_List() is used, as opposed # to just checking if failed_intf is in D.red_next_hops,

#failed_intfがD.red_next_hopsにあるかどうかを単にチェックするのではなく、Is_Remote_Node_In_NH_List()が使用されます。

                # because failed_intf could be marked as MRT_INELIGIBLE.
                elif Is_Remote_Node_In_NH_List(F, D.red_next_hops):
                    Copy_List_Items(alt.nh_list, D.blue_next_hops)
                    alt.fec = 'BLUE'
                    alt.prot = 'LINK_PROTECTION'
                elif Is_Remote_Node_In_NH_List(F, D.blue_next_hops):
                    Copy_List_Items(alt.nh_list, D.red_next_hops)
                    alt.fec = 'RED'
                    alt.prot = 'LINK_PROTECTION'
                else:
                    alt.fec = random.choice(['RED','BLUE'])
                    alt.prot = 'LINK_PROTECTION'
        

D.alt_list.append(alt)

D.alt_list.append(alt)

def Write_GADAG_To_File(topo, file_prefix):
    gadag_edge_list = []
    for node in topo.node_list:
        for intf in node.intf_list:
            if intf.SIMULATION_OUTGOING:
                local_node =  "%04d" % (intf.local_node.node_id)
                remote_node = "%04d" % (intf.remote_node.node_id)
                intf_data = "%03d" % (intf.link_data)
                edge_string=(local_node+','+remote_node+','+
                             intf_data+'\n')
                gadag_edge_list.append(edge_string)
    gadag_edge_list.sort();
    filename = file_prefix + '_gadag.csv'
    with open(filename, 'w') as gadag_file:
        gadag_file.write('local_node,'\
                         'remote_node,local_intf_link_data\n')
        for edge_string in gadag_edge_list:
            gadag_file.write(edge_string);
        
def Write_MRTs_For_All_Dests_To_File(topo, color, file_prefix):
    edge_list = []
    for node in topo.island_node_list_for_test_gr:
        if color == 'blue':
            node_next_hops_dict = node.blue_next_hops_dict
        elif color == 'red':
            node_next_hops_dict = node.red_next_hops_dict
        for dest_node_id in node_next_hops_dict:
            for intf in node_next_hops_dict[dest_node_id]:
                gadag_root =  "%04d" % (topo.gadag_root.node_id)
                dest_node =  "%04d" % (dest_node_id)
                local_node =  "%04d" % (intf.local_node.node_id)
                remote_node = "%04d" % (intf.remote_node.node_id)
                intf_data = "%03d" % (intf.link_data)
                edge_string=(gadag_root+','+dest_node+','+local_node+
                               ','+remote_node+','+intf_data+'\n')
                edge_list.append(edge_string)
    edge_list.sort()
    filename = file_prefix + '_' + color + '_to_all.csv'
    with open(filename, 'w') as mrt_file:
        mrt_file.write('gadag_root,dest,'\
            'local_node,remote_node,link_data\n')
        for edge_string in edge_list:
            mrt_file.write(edge_string);
        

def Write_Both_MRTs_For_All_Dests_To_File(topo, file_prefix): Write_MRTs_For_All_Dests_To_File(topo, 'blue', file_prefix) Write_MRTs_For_All_Dests_To_File(topo, 'red', file_prefix)

def Write_Both_MRTs_For_All_Dests_To_File(topo、file_prefix):Write_MRTs_For_All_Dests_To_File(topo、 'blue'、file_prefix)Write_MRTs_For_All_Dests_To_File(topo、 'red'、file_prefix)

def Write_Alternates_For_All_Dests_To_File(topo, file_prefix):
    edge_list = []
    for x in topo.island_node_list_for_test_gr:
        for dest_node_id in x.alt_dict:
            alt_list = x.alt_dict[dest_node_id]
            for alt in alt_list:
                for alt_intf in alt.nh_list:
                    gadag_root =  "%04d" % (topo.gadag_root.node_id)
                    dest_node =  "%04d" % (dest_node_id)
                    prim_local_node =  \
                        "%04d" % (alt.failed_intf.local_node.node_id)
                    prim_remote_node = \
                        "%04d" % (alt.failed_intf.remote_node.node_id)
                    prim_intf_data = \
                        "%03d" % (alt.failed_intf.link_data)
                    if alt_intf == None:
                        alt_local_node = "None"
                        alt_remote_node = "None"
                        alt_intf_data = "None"
                    else:
                        alt_local_node = \
                            "%04d" % (alt_intf.local_node.node_id)
                        alt_remote_node = \
                            "%04d" % (alt_intf.remote_node.node_id)
                        alt_intf_data = \
                            "%03d" % (alt_intf.link_data)
                    edge_string = (gadag_root+','+dest_node+','+
                        prim_local_node+','+prim_remote_node+','+
                        prim_intf_data+','+alt_local_node+','+
                        alt_remote_node+','+alt_intf_data+','+
                        alt.fec +'\n')
                    edge_list.append(edge_string)
    edge_list.sort()
    filename = file_prefix + '_alts_to_all.csv'
    with open(filename, 'w') as alt_file:
        alt_file.write('gadag_root,dest,'\
            'prim_nh.local_node,prim_nh.remote_node,'\
            'prim_nh.link_data,alt_nh.local_node,'\
            'alt_nh.remote_node,alt_nh.link_data,'\
            'alt_nh.fec\n')
        for edge_string in edge_list:
            alt_file.write(edge_string);
        

def Raise_GADAG_Root_Selection_Priority(topo,node_id): node = topo.node_dict[node_id] node.GR_sel_priority = 255

def Raise_GADAG_Root_Selection_Priority(topo、node_id):node = topo.node_dict [node_id] node.GR_sel_priority = 255

def Lower_GADAG_Root_Selection_Priority(topo,node_id): node = topo.node_dict[node_id] node.GR_sel_priority = 128

def Lower_GADAG_Root_Selection_Priority(topo、node_id):node = topo.node_dict [node_id] node.GR_sel_priority = 128

def GADAG_Root_Compare(node_a, node_b):
    if (node_a.GR_sel_priority > node_b.GR_sel_priority):
        return 1
    elif (node_a.GR_sel_priority < node_b.GR_sel_priority):
        return -1
    else:
        if node_a.node_id > node_b.node_id:
            return 1
        elif node_a.node_id < node_b.node_id:
            return -1
        
def Set_GADAG_Root(topo,computing_router):
    gadag_root_list = []
    for node in topo.island_node_list:
        gadag_root_list.append(node)
    gadag_root_list.sort(GADAG_Root_Compare)
    topo.gadag_root = gadag_root_list.pop()
        
def Add_Prefix_Advertisements_From_File(topo, filename):
    prefix_filename = filename + '.prefix'
    cols_list = []
    if not os.path.exists(prefix_filename):
        return
    with open(prefix_filename) as prefix_file:
        for line in prefix_file:
            line = line.rstrip('\r\n')
            cols=line.split(',')
            cols_list.append(cols)
            prefix_id = int(cols[0])
            if prefix_id < 2000 or prefix_id >2999:
        

print('skipping the following line of prefix file') print('prefix id should be between 2000 and 2999') print(line) continue prefix_node_id = int(cols[1]) prefix_cost = int(cols[2]) advertising_node = topo.node_dict[prefix_node_id] advertising_node.prefix_cost_dict[prefix_id] = prefix_cost

print( '接頭辞ファイルの次の行をスキップする')print( '接頭辞IDは2000から2999の間でなければなりません')print(line)continue prefix_node_id = int(cols [1])prefix_cost = int(cols [2])Advertising_node = topo.node_dict [prefix_node_id] Advertising_node.prefix_cost_dict [prefix_id] = prefix_cost

def Add_Prefixes_for_Non_Island_Nodes(topo): for node in topo.node_list: if node.IN_MRT_ISLAND: continue prefix_id = node.node_id + 1000 node.prefix_cost_dict[prefix_id] = 0

def Add_Prefixes_for_Non_Island_Nodes(topo):for node in topo.node_list:if node.IN_MRT_ISLAND:continue prefix_id = node.node_id + 1000 node.prefix_cost_dict [prefix_id] = 0

def Add_Profile_IDs_from_File(topo, filename):
    profile_filename = filename + '.profile'
    for node in topo.node_list:
        node.profile_id_list = []
    cols_list = []
    if os.path.exists(profile_filename):
        with open(profile_filename) as profile_file:
            for line in profile_file:
                line = line.rstrip('\r\n')
                cols=line.split(',')
                cols_list.append(cols)
                node_id = int(cols[0])
                profile_id = int(cols[1])
                this_node = topo.node_dict[node_id]
                this_node.profile_id_list.append(profile_id)
    else:
        for node in topo.node_list:
            node.profile_id_list = [0]
        
def Island_Marking_SPF(topo,spf_root):
    spf_root.isl_marking_spf_dict = {}
    for y in topo.node_list:
        y.spf_metric = 2147483647 # 2^31-1 as max metric
        y.PATH_HITS_ISLAND = False
        y.next_hops = []
        y.spf_visited = False
    spf_root.spf_metric = 0
    spf_heap = []
    heapq.heappush(spf_heap,
                   (spf_root.spf_metric,spf_root.node_id,spf_root) )
    while spf_heap != []:
        #extract third element of tuple popped from heap
        min_node = heapq.heappop(spf_heap)[2]
        if min_node.spf_visited:
            continue
        min_node.spf_visited = True
        spf_root.isl_marking_spf_dict[min_node.node_id] = \
            (min_node.spf_metric, min_node.PATH_HITS_ISLAND)
        for intf in min_node.intf_list:
            path_metric = min_node.spf_metric + intf.metric
            if path_metric < intf.remote_node.spf_metric:
                intf.remote_node.spf_metric = path_metric
                if min_node is spf_root:
                    intf.remote_node.next_hops = [intf]
                else:
                    Copy_List_Items(intf.remote_node.next_hops,
                                    min_node.next_hops)
                if (intf.remote_node.IN_MRT_ISLAND):
                    intf.remote_node.PATH_HITS_ISLAND = True
                else:
                    intf.remote_node.PATH_HITS_ISLAND = \
                        min_node.PATH_HITS_ISLAND
                heapq.heappush(spf_heap,
                               ( intf.remote_node.spf_metric,
                                 intf.remote_node.node_id,
                                 intf.remote_node ) )
            elif path_metric == intf.remote_node.spf_metric:
                if min_node is spf_root:
                    Add_Item_To_List_If_New(
                        intf.remote_node.next_hops,intf)
                else:
                    for nh_intf in min_node.next_hops:
                        Add_Item_To_List_If_New(
                            intf.remote_node.next_hops,nh_intf)
                if (intf.remote_node.IN_MRT_ISLAND):
                    intf.remote_node.PATH_HITS_ISLAND = True
                else:
                    if (intf.remote_node.PATH_HITS_ISLAND
                        or min_node.PATH_HITS_ISLAND):
                        intf.remote_node.PATH_HITS_ISLAND = True
        
def Create_Basic_Named_Proxy_Nodes(topo):
    for node in topo.node_list:
        for prefix in node.prefix_cost_dict:
            prefix_cost = node.prefix_cost_dict[prefix]
            if prefix in topo.named_proxy_dict:
                P = topo.named_proxy_dict[prefix]
                P.node_prefix_cost_list.append((node,prefix_cost))
            else:
                P = Named_Proxy_Node()
                topo.named_proxy_dict[prefix] = P
                P.node_id = prefix
                P.node_prefix_cost_list = [(node,prefix_cost)]
        
def Compute_Loop_Free_Island_Neighbors_For_Each_Prefix(topo):
    topo.island_nbr_set = set()
    topo.island_border_set = set()
    for node in topo.node_list:
        if node.IN_MRT_ISLAND:
            continue
        for intf in node.intf_list:
            if intf.remote_node.IN_MRT_ISLAND:
                topo.island_nbr_set.add(node)
                topo.island_border_set.add(intf.remote_node)
        

for island_nbr in topo.island_nbr_set: Island_Marking_SPF(topo,island_nbr)

topo.island_nbr_setのisland_nbrの場合:Island_Marking_SPF(topo、island_nbr)

    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        P.lfin_list = []
        for island_nbr in topo.island_nbr_set:
            min_isl_nbr_to_pref_cost = 2147483647
            for (adv_node, prefix_cost) in P.node_prefix_cost_list:
                (adv_node_cost, path_hits_island) = \
                    island_nbr.isl_marking_spf_dict[adv_node.node_id]
                isl_nbr_to_pref_cost = adv_node_cost + prefix_cost
                if isl_nbr_to_pref_cost < min_isl_nbr_to_pref_cost:
                    min_isl_nbr_to_pref_cost = isl_nbr_to_pref_cost
                    min_path_hits_island = path_hits_island
                elif isl_nbr_to_pref_cost == min_isl_nbr_to_pref_cost:
                    if min_path_hits_island or path_hits_island:
                        min_path_hits_island = True
            if not min_path_hits_island:
                P.lfin_list.append( (island_nbr,
                                     min_isl_nbr_to_pref_cost) )
        
def Compute_Island_Border_Router_LFIN_Pairs_For_Each_Prefix(topo):
    for ibr in topo.island_border_set:
        ibr.prefix_lfin_dict = {}
        ibr.min_intf_metric_dict = {}
        ibr.min_intf_list_dict = {}
        ibr.min_intf_list_dict[None] = None
        for intf in ibr.intf_list:
            if not intf.remote_node in topo.island_nbr_set:
                continue
            if not intf.remote_node in ibr.min_intf_metric_dict:
        
                ibr.min_intf_metric_dict[intf.remote_node] = \
                    intf.metric
                ibr.min_intf_list_dict[intf.remote_node] = [intf]
            else:
                if (intf.metric
                    < ibr.min_intf_metric_dict[intf.remote_node]):
                    ibr.min_intf_metric_dict[intf.remote_node] = \
                         intf.metric
                    ibr.min_intf_list_dict[intf.remote_node] = [intf]
                elif (intf.metric
                      < ibr.min_intf_metric_dict[intf.remote_node]):
                    ibr.min_intf_list_dict[intf.remote_node].\
                        append(intf)
        
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        for ibr in topo.island_border_set:
            min_ibr_lfin_pref_cost = 2147483647
            min_lfin = None
            for (lfin, lfin_to_pref_cost) in P.lfin_list:
                if not lfin in ibr.min_intf_metric_dict:
                    continue
                ibr_lfin_pref_cost = \
                    ibr.min_intf_metric_dict[lfin] + lfin_to_pref_cost
                if ibr_lfin_pref_cost < min_ibr_lfin_pref_cost:
                    min_ibr_lfin_pref_cost = ibr_lfin_pref_cost
                    min_lfin = lfin
            ibr.prefix_lfin_dict[prefix] = (min_lfin,
                min_ibr_lfin_pref_cost,
                ibr.min_intf_list_dict[min_lfin])
        
def Proxy_Node_Att_Router_Compare(pnar_a, pnar_b):
    if pnar_a.named_proxy_cost < pnar_b.named_proxy_cost:
        return -1
    if pnar_b.named_proxy_cost < pnar_a.named_proxy_cost:
        return 1
    if pnar_a.node.node_id < pnar_b.node.node_id:
        return -1
    if pnar_b.node.node_id < pnar_a.node.node_id:
        return 1
    if pnar_a.min_lfin == None:
        return -1
    if pnar_b.min_lfin == None:
        return 1
        
def Choose_Proxy_Node_Attachment_Routers(topo):
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        pnar_candidate_list = []
        for (node, prefix_cost) in P.node_prefix_cost_list:
            if not node.IN_MRT_ISLAND:
                continue
            pnar = Proxy_Node_Attachment_Router()
            pnar.prefix = prefix
            pnar.named_proxy_cost = prefix_cost
            pnar.node = node
            pnar_candidate_list.append(pnar)
        for ibr in topo.island_border_set:
            (min_lfin, prefix_cost, min_intf_list) = \
                ibr.prefix_lfin_dict[prefix]
            if min_lfin == None:
                continue
            pnar = Proxy_Node_Attachment_Router()
            pnar.named_proxy_cost = prefix_cost
            pnar.node = ibr
            pnar.min_lfin = min_lfin
            pnar.nh_intf_list = min_intf_list
            pnar_candidate_list.append(pnar)
        pnar_candidate_list.sort(cmp=Proxy_Node_Att_Router_Compare)
        #pop first element from list
        first_pnar = pnar_candidate_list.pop(0)
        second_pnar = None
        for next_pnar in pnar_candidate_list:
            if next_pnar.node is first_pnar.node:
                continue
            second_pnar = next_pnar
            break
        

P.pnar1 = first_pnar P.pnar2 = second_pnar

P.pnar1 = first_pnar P.pnar2 = second_pnar

def Attach_Named_Proxy_Nodes(topo): Compute_Loop_Free_Island_Neighbors_For_Each_Prefix(topo) Compute_Island_Border_Router_LFIN_Pairs_For_Each_Prefix(topo) Choose_Proxy_Node_Attachment_Routers(topo)

def Attach_Named_Proxy_Nodes(topo):Compute_Loop_Free_Island_Neighbors_For_Each_Prefix(topo)Compute_Island_Border_Router_LFIN_Pairs_For_Each_Prefix(topo)Choose_Proxy_Node_Attachment_Routers(topo)

def Select_Proxy_Node_NHs(P,S):
    if P.pnar1.node.node_id < P.pnar2.node.node_id:
        X = P.pnar1.node
        Y = P.pnar2.node
    else:
        X = P.pnar2.node
        Y = P.pnar1.node
    P.pnar_X = X
    P.pnar_Y = Y
    A = X.order_proxy
    B = Y.order_proxy
    if (A is S.localroot
        and B is S.localroot):
        #print("1.0")
        Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
        Copy_List_Items(P.red_next_hops, Y.red_next_hops)
        return
    if (A is S.localroot
        and B is not S.localroot):
        #print("2.0")
        if B.LOWER:
            #print("2.1")
            Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
            Copy_List_Items(P.red_next_hops, Y.red_next_hops)
            return
        if B.HIGHER:
            #print("2.2")
            Copy_List_Items(P.blue_next_hops, X.red_next_hops)
            Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
            return
        else:
            #print("2.3")
            Copy_List_Items(P.blue_next_hops, X.red_next_hops)
            Copy_List_Items(P.red_next_hops, Y.red_next_hops)
            return
    if (A is not S.localroot
        and B is S.localroot):
        #print("3.0")
        if A.LOWER:
            #print("3.1")
            Copy_List_Items(P.blue_next_hops, X.red_next_hops)
            Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
            return
        if A.HIGHER:
            #print("3.2")
            Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
            Copy_List_Items(P.red_next_hops, Y.red_next_hops)
            return
        else:
            #print("3.3")
            Copy_List_Items(P.blue_next_hops, X.red_next_hops)
            Copy_List_Items(P.red_next_hops, Y.red_next_hops)
            return
    if (A is not S.localroot
        and B is not S.localroot):
        #print("4.0")
        if (S is A.localroot or S is B.localroot):
            #print("4.05")
            if A.topo_order < B.topo_order:
                #print("4.05.1")
                Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                return
            else:
                #print("4.05.2")
                Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                return
        if A.LOWER:
            #print("4.1")
            if B.HIGHER:
                #print("4.1.1")
                Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                return
            if B.LOWER:
                #print("4.1.2")
                if A.topo_order < B.topo_order:
                    #print("4.1.2.1")
                    Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                    Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                    return
                else:
                    #print("4.1.2.2")
                    Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                    Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                    return
            else:
                #print("4.1.3")
                Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                return
        if A.HIGHER:
            #print("4.2")
            if B.HIGHER:
                #print("4.2.1")
                if A.topo_order < B.topo_order:
                    #print("4.2.1.1")
                    Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                    Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                    return
                else:
                    #print("4.2.1.2")
                    Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                    Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                    return
        
            if B.LOWER:
                #print("4.2.2")
                Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                return
            else:
                #print("4.2.3")
                Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                return
        else:
            #print("4.3")
            if B.LOWER:
                #print("4.3.1")
                Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                return
            if B.HIGHER:
                #print("4.3.2")
                Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                return
            else:
                #print("4.3.3")
                if A.topo_order < B.topo_order:
                    #print("4.3.3.1")
                    Copy_List_Items(P.blue_next_hops, X.blue_next_hops)
                    Copy_List_Items(P.red_next_hops, Y.red_next_hops)
                    return
                else:
                    #print("4.3.3.2")
                    Copy_List_Items(P.blue_next_hops, X.red_next_hops)
                    Copy_List_Items(P.red_next_hops, Y.blue_next_hops)
                    return
    assert(False)
        

def Compute_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,S): for prefix in topo.named_proxy_dict: P = topo.named_proxy_dict[prefix] if P.pnar2 == None: if S is P.pnar1.node: # set the MRT next hops for the PNAR to # reach the LFIN and change FEC to green Copy_List_Items(P.blue_next_hops, P.pnar1.nh_intf_list) S.blue_to_green_nh_dict[P.node_id] = True Copy_List_Items(P.red_next_hops, P.pnar1.nh_intf_list)

def Compute_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(topo、S):for prefix in topo.named_proxy_dict:P = topo.named_proxy_dict [prefix] if P.pnar2 == None:if S is P.pnar1.node:#set the MRT next-hops for the PN #LFINに到達し、FECを緑色に変更しますCopy_List_Items(P.blue_next_hops、P.pnar1.nh_intf_list)S.blue_to_green_nh_dict [P.node_id] = True Copy_List_Items(P.red_next_hops、P.pnar1.nh_intf_list)

                S.red_to_green_nh_dict[P.node_id] = True
            else:
                # inherit MRT NHs for P from pnar1
                Copy_List_Items(P.blue_next_hops,
                                P.pnar1.node.blue_next_hops)
                Copy_List_Items(P.red_next_hops,
                                P.pnar1.node.red_next_hops)
        else:
            Select_Proxy_Node_NHs(P,S)
            # set the MRT next hops for the PNAR to reach the LFIN
            # and change FEC to green rely on the red or blue
            # next hops being empty to figure out which one needs
            # to point to the LFIN.
            if S is P.pnar1.node:
                this_pnar = P.pnar1
            elif S is P.pnar2.node:
                this_pnar = P.pnar2
            else:
                continue
            if P.blue_next_hops == []:
                Copy_List_Items(P.blue_next_hops,
                    this_pnar.nh_intf_list)
                S.blue_to_green_nh_dict[P.node_id] = True
            if P.red_next_hops == []:
                Copy_List_Items(P.red_next_hops,
                    this_pnar.nh_intf_list)
                S.red_to_green_nh_dict[P.node_id] = True
        

def Select_Alternates_Proxy_Node(P,F,primary_intf): S = primary_intf.local_node X = P.pnar_X Y = P.pnar_Y A = X.order_proxy B = Y.order_proxy if F is A and F is B: return 'PRIM_NH_IS_OP_FOR_BOTH_X_AND_Y' if F is A: return 'USE_RED' if F is B: return 'USE_BLUE'

def Select_Alternates_Proxy_Node(P、F、primary_intf):S = primary_intf.local_node X = P.pnar_X Y = P.pnar_Y A = X.order_proxy B = Y.order_proxy if F is A and F is B:return 'PRIM_NH_IS_OP_FOR_BOTH_X_AND_Y' is A:FがBの場合は「USE_RED」を返す:「USE_BLUE」を返す

if not In_Common_Block(A, B): if In_Common_Block(F, A): return 'USE_RED' elif In_Common_Block(F, B): return 'USE_BLUE' else: return 'USE_RED_OR_BLUE'

if In_Common_Block(A、B):if In_Common_Block(F、A):return 'USE_RED' elif In_Common_Block(F、B):return 'USE_BLUE' else:return 'USE_RED_OR_BLUE'

if (not In_Common_Block(F, A) and not In_Common_Block(F, A) ): return 'USE_RED_OR_BLUE'

if(In_Common_Block(F、A)ではなく、In_Common_Block(F、A)ではない):return 'USE_RED_OR_BLUE'

    alt_to_X = Select_Alternates(X, F, primary_intf)
    alt_to_Y = Select_Alternates(Y, F, primary_intf)
        
    if (alt_to_X == 'USE_RED_OR_BLUE'
        and alt_to_Y == 'USE_RED_OR_BLUE'):
        return 'USE_RED_OR_BLUE'
    if alt_to_X == 'USE_RED_OR_BLUE':
        return 'USE_BLUE'
    if alt_to_Y == 'USE_RED_OR_BLUE':
        return 'USE_RED'
        
    if (A is S.localroot
        and B is S.localroot):
        #print("1.0")
        if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
            return 'USE_RED_OR_BLUE'
        if alt_to_X == 'USE_BLUE':
            return 'USE_BLUE'
        if alt_to_Y == 'USE_RED':
            return 'USE_RED'
        assert(False)
    if (A is S.localroot
        and B is not S.localroot):
        #print("2.0")
        if B.LOWER:
            #print("2.1")
            if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
                return 'USE_RED_OR_BLUE'
            if alt_to_X == 'USE_BLUE':
                return 'USE_BLUE'
            if alt_to_Y == 'USE_RED':
                return 'USE_RED'
            assert(False)
        if B.HIGHER:
            #print("2.2")
            if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                return 'USE_RED_OR_BLUE'
            if alt_to_X == 'USE_RED':
                return 'USE_BLUE'
            if alt_to_Y == 'USE_BLUE':
                return 'USE_RED'
            assert(False)
        else:
            #print("2.3")
            if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_RED'):
                return 'USE_RED_OR_BLUE'
            if alt_to_X == 'USE_RED':
                return 'USE_BLUE'
            if alt_to_Y == 'USE_RED':
                return 'USE_RED'
            assert(False)
    if (A is not S.localroot
        and B is S.localroot):
        #print("3.0")
        if A.LOWER:
            #print("3.1")
            if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                return 'USE_RED_OR_BLUE'
            if alt_to_X == 'USE_RED':
                return 'USE_BLUE'
            if alt_to_Y == 'USE_BLUE':
                return 'USE_RED'
            assert(False)
        if A.HIGHER:
            #print("3.2")
            if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
                return 'USE_RED_OR_BLUE'
            if alt_to_X == 'USE_BLUE':
                return 'USE_BLUE'
            if alt_to_Y == 'USE_RED':
                return 'USE_RED'
            assert(False)
        else:
            #print("3.3")
            if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_RED'):
                return 'USE_RED_OR_BLUE'
            if alt_to_X == 'USE_RED':
                return 'USE_BLUE'
            if alt_to_Y == 'USE_RED':
                return 'USE_RED'
            assert(False)
    if (A is not S.localroot
        and B is not S.localroot):
        #print("4.0")
        if (S is A.localroot or S is B.localroot):
            #print("4.05")
            if A.topo_order < B.topo_order:
                #print("4.05.1")
                if (alt_to_X == 'USE_BLUE' and alt_to_Y == 'USE_RED'):
                    return 'USE_RED_OR_BLUE'
                if alt_to_X == 'USE_BLUE':
                    return 'USE_BLUE'
        
                if alt_to_Y == 'USE_RED':
                    return 'USE_RED'
                assert(False)
            else:
                #print("4.05.2")
                if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                    return 'USE_RED_OR_BLUE'
                if alt_to_X == 'USE_RED':
                    return 'USE_BLUE'
                if alt_to_Y == 'USE_BLUE':
                    return 'USE_RED'
                assert(False)
        if A.LOWER:
            #print("4.1")
            if B.HIGHER:
                #print("4.1.1")
                if (alt_to_X == 'USE_RED' and alt_to_Y == 'USE_BLUE'):
                    return 'USE_RED_OR_BLUE'
                if alt_to_X == 'USE_RED':
                    return 'USE_BLUE'
                if alt_to_Y == 'USE_BLUE':
                    return 'USE_RED'
                assert(False)
            if B.LOWER:
                #print("4.1.2")
                if A.topo_order < B.topo_order:
                    #print("4.1.2.1")
                    if (alt_to_X == 'USE_BLUE'
                        and alt_to_Y == 'USE_RED'):
                        return 'USE_RED_OR_BLUE'
                    if alt_to_X == 'USE_BLUE':
                        return 'USE_BLUE'
                    if alt_to_Y == 'USE_RED':
                        return 'USE_RED'
                    assert(False)
                else:
                    #print("4.1.2.2")
                    if (alt_to_X == 'USE_RED'
                        and alt_to_Y == 'USE_BLUE'):
                        return 'USE_RED_OR_BLUE'
                    if alt_to_X == 'USE_RED':
                        return 'USE_BLUE'
                    if alt_to_Y == 'USE_BLUE':
                        return 'USE_RED'
                    assert(False)
            else:
                #print("4.1.3")
                if (F.LOWER and not F.HIGHER
        
                    and F.topo_order > A.topo_order):
                    #print("4.1.3.1")
                    return 'USE_RED'
                else:
                    #print("4.1.3.2")
                    return 'USE_BLUE'
        if A.HIGHER:
            #print("4.2")
            if B.HIGHER:
                #print("4.2.1")
                if A.topo_order < B.topo_order:
                    #print("4.2.1.1")
                    if (alt_to_X == 'USE_BLUE'
                        and alt_to_Y == 'USE_RED'):
                        return 'USE_RED_OR_BLUE'
                    if alt_to_X == 'USE_BLUE':
                        return 'USE_BLUE'
                    if alt_to_Y == 'USE_RED':
                        return 'USE_RED'
                    assert(False)
                else:
                    #print("4.2.1.2")
                    if (alt_to_X == 'USE_RED'
                        and alt_to_Y == 'USE_BLUE'):
                        return 'USE_RED_OR_BLUE'
                    if alt_to_X == 'USE_RED':
                        return 'USE_BLUE'
                    if alt_to_Y == 'USE_BLUE':
                        return 'USE_RED'
                    assert(False)
            if B.LOWER:
                #print("4.2.2")
                if (alt_to_X == 'USE_BLUE'
                    and alt_to_Y == 'USE_RED'):
                    return 'USE_RED_OR_BLUE'
                if alt_to_X == 'USE_BLUE':
                    return 'USE_BLUE'
                if alt_to_Y == 'USE_RED':
                    return 'USE_RED'
                assert(False)
            else:
                #print("4.2.3")
                if (F.HIGHER and not F.LOWER
                    and F.topo_order < A.topo_order):
                    return 'USE_RED'
                else:
                    return 'USE_BLUE'
        
        else:
            #print("4.3")
            if B.LOWER:
                #print("4.3.1")
                if (F.LOWER and not F.HIGHER
                    and F.topo_order > B.topo_order):
                    return 'USE_BLUE'
                else:
                    return 'USE_RED'
            if B.HIGHER:
                #print("4.3.2")
                if (F.HIGHER and not F.LOWER
                    and F.topo_order < B.topo_order):
                    return 'USE_BLUE'
                else:
                    return 'USE_RED'
            else:
                #print("4.3.3")
                if A.topo_order < B.topo_order:
                    #print("4.3.3.1")
                    if (alt_to_X == 'USE_BLUE'
                        and alt_to_Y == 'USE_RED'):
                        return 'USE_RED_OR_BLUE'
                    if alt_to_X == 'USE_BLUE':
                        return 'USE_BLUE'
                    if alt_to_Y == 'USE_RED':
                        return 'USE_RED'
                    assert(False)
                else:
                    #print("4.3.3.2")
                    if (alt_to_X == 'USE_RED'
                        and alt_to_Y == 'USE_BLUE'):
                        return 'USE_RED_OR_BLUE'
                    if alt_to_X == 'USE_RED':
                        return 'USE_BLUE'
                    if alt_to_Y == 'USE_BLUE':
                        return 'USE_RED'
                    assert(False)
    assert(False)
        
def Compute_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src):
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        min_total_pref_cost = 2147483647
        for (adv_node, prefix_cost) in P.node_prefix_cost_list:
            total_pref_cost = (adv_node.primary_spf_metric
                               + prefix_cost)
            if total_pref_cost < min_total_pref_cost:
        

min_total_pref_cost = total_pref_cost Copy_List_Items(P.primary_next_hops, adv_node.primary_next_hops) elif total_pref_cost == min_total_pref_cost: for nh_intf in adv_node.primary_next_hops: Add_Item_To_List_If_New(P.primary_next_hops, nh_intf)

min_total_pref_cost = total_pref_cost Copy_List_Items(P.primary_next_hops、adv_node.primary_next_hops)elif total_pref_cost == min_total_pref_cost:for nh_intf in adv_node.primary_next_hops:Add_Item_To_List_Prim_New_Phop_New_Phop_Inf_Phop_New_Ph_Phop_In_Priv_New_Phop_In_Priv_New_Phop_In_Ph_P_New_Phop_In_Ph_In_Ph_Ph_PHO_INT_PRY_HOP_INT_PHO_INT_PHOTO_PINT_NEW_HINT_HINT_HINT_HINT_HINT_HINT_HINT_PHOTO

def Select_Alts_For_One_Src_To_Named_Proxy_Nodes(topo,src):
    for prefix in topo.named_proxy_dict:
        P = topo.named_proxy_dict[prefix]
        P.alt_list = []
        for failed_intf in P.primary_next_hops:
            alt = Alternate()
            alt.failed_intf = failed_intf
            if failed_intf not in src.island_intf_list:
                alt.info = 'PRIM_NH_FOR_PROXY_NODE_NOT_IN_ISLAND'
            elif P.pnar1 is None:
                alt.info = 'NO_PNARs_EXIST_FOR_THIS_PREFIX'
            elif src is P.pnar1.node:
                alt.info = 'SRC_IS_PNAR'
            elif P.pnar2 is not None and src is P.pnar2.node:
                alt.info = 'SRC_IS_PNAR'
            elif P.pnar2 is None:
                #inherit alternates from the only pnar.
                alt.info = Select_Alternates(P.pnar1.node,
                            failed_intf.remote_node, failed_intf)
            elif failed_intf in src.island_intf_list:
                alt.info = Select_Alternates_Proxy_Node(P,
                            failed_intf.remote_node, failed_intf)
        
            if alt.info == 'USE_RED_OR_BLUE':
                alt.red_or_blue = \
                    random.choice(['USE_RED','USE_BLUE'])
            if (alt.info == 'USE_BLUE'
                or alt.red_or_blue == 'USE_BLUE'):
                Copy_List_Items(alt.nh_list, P.blue_next_hops)
                alt.fec = 'BLUE'
                alt.prot = 'NODE_PROTECTION'
            elif (alt.info == 'USE_RED'
                  or alt.red_or_blue == 'USE_RED'):
                Copy_List_Items(alt.nh_list, P.red_next_hops)
                alt.fec = 'RED'
                alt.prot = 'NODE_PROTECTION'
            elif (alt.info == 'PRIM_NH_IS_D_OR_OP_FOR_D'
                or alt.info == 'PRIM_NH_IS_OP_FOR_BOTH_X_AND_Y'):
                if failed_intf.OUTGOING and failed_intf.INCOMING:
                    # cut-link: if there are parallel cut links, use
        
                    # the link(s) with lowest metric that are not
                    # primary intf or None
                    cand_alt_list = [None]
                    min_metric = 2147483647
                    for intf in src.island_intf_list:
                        if ( intf is not failed_intf and
                             (intf.remote_node is
                             failed_intf.remote_node)):
                            if intf.metric < min_metric:
                                cand_alt_list = [intf]
                                min_metric = intf.metric
                            elif intf.metric == min_metric:
                                cand_alt_list.append(intf)
                    if cand_alt_list != [None]:
                        alt.fec = 'GREEN'
                        alt.prot = 'PARALLEL_CUTLINK'
                    else:
                        alt.fec = 'NO_ALTERNATE'
                        alt.prot = 'NO_PROTECTION'
                    Copy_List_Items(alt.nh_list, cand_alt_list)
                else:
                    # set Z as the node to inherit blue next hops from
                    if alt.info == 'PRIM_NH_IS_D_OR_OP_FOR_D':
                        Z = P.pnar1.node
                    else:
                        Z = P
                    if failed_intf in Z.red_next_hops:
                        Copy_List_Items(alt.nh_list, Z.blue_next_hops)
                        alt.fec = 'BLUE'
                        alt.prot = 'LINK_PROTECTION'
                    else:
                        assert(failed_intf in Z.blue_next_hops)
                        Copy_List_Items(alt.nh_list, Z.red_next_hops)
                        alt.fec = 'RED'
                        alt.prot = 'LINK_PROTECTION'
        
            elif alt.info == 'PRIM_NH_FOR_PROXY_NODE_NOT_IN_ISLAND':
                if (P.pnar2 == None and src is P.pnar1.node):
                    #MRT Island is singly connected to non-island dest
                    alt.fec = 'NO_ALTERNATE'
                    alt.prot = 'NO_PROTECTION'
                elif P.node_id in src.blue_to_green_nh_dict:
                    # blue to P goes to failed LFIN so use red to P
                    Copy_List_Items(alt.nh_list, P.red_next_hops)
                    alt.fec = 'RED'
                    alt.prot = 'LINK_PROTECTION'
                elif P.node_id in src.red_to_green_nh_dict:
                    # red to P goes to failed LFIN so use blue to P
                    Copy_List_Items(alt.nh_list, P.blue_next_hops)
                    alt.fec = 'BLUE'
                    alt.prot = 'LINK_PROTECTION'
                else:
                    Copy_List_Items(alt.nh_list, P.blue_next_hops)
                    alt.fec = 'BLUE'
                    alt.prot = 'LINK_PROTECTION'
            elif alt.info == 'TEMP_NO_ALTERNATE':
                alt.fec = 'NO_ALTERNATE'
                alt.prot = 'NO_PROTECTION'
        

P.alt_list.append(alt)

P.alt_list.append(alt)

def Run_Basic_MRT_for_One_Source(topo, src): MRT_Island_Identification(topo, src, 0, 0) Set_Island_Intf_and_Node_Lists(topo) Set_GADAG_Root(topo,src) Sort_Interfaces(topo) Run_Lowpoint(topo) Assign_Remaining_Lowpoint_Parents(topo) Construct_GADAG_via_Lowpoint(topo) Run_Assign_Block_ID(topo) Add_Undirected_Links(topo) Compute_MRT_NH_For_One_Src_To_Island_Dests(topo,src) Store_MRT_Nexthops_For_One_Src_To_Island_Dests(topo,src) Select_Alts_For_One_Src_To_Island_Dests(topo,src) Store_Primary_and_Alts_For_One_Src_To_Island_Dests(topo,src)

DEF Run_Basic_MRT_for_One_Source(TOPO、SRC):MRT_Island_Identification(TOPO、SRC、0、0)Set_Island_Intf_and_Node_Lists(TOPO)Set_GADAG_Root(TOPO、SRC)Sort_Interfaces(TOPO)Run_Lowpoint(TOPO)Assign_Remaining_Lowpoint_Parents(TOPO)Construct_GADAG_via_Lowpoint(TOPO)Run_Assign_Block_ID(TOPO)Add_Undirected_Links( topo)Compute_MRT_NH_For_One_Src_To_Island_Dests(topo、src)Store_MRT_Nexthops_For_One_Src_To_Island_Dests(topo、src)Select_Alts_For_One_Src_To_Island_Dests(topo、src_To_Island_Dests(topo、src_To_Island_Dests(topo、src_To_Src_To_Src_To_Island_Drc)

def Store_GADAG_and_Named_Proxies_Once(topo): for node in topo.node_list: for intf in node.intf_list: if intf.OUTGOING: intf.SIMULATION_OUTGOING = True else: intf.SIMULATION_OUTGOING = False for prefix in topo.named_proxy_dict: P = topo.named_proxy_dict[prefix] topo.stored_named_proxy_dict[prefix] = P

def Store_GADAG_and_Named_Proxies_Once(topo):for node in topo.node_list:for intf in node.intf_list:if intf.OUTGOING:intf.SIMULATION_OUTGOING = True else:intf.SIMULATION_OUTGOING = False for prefix in topo.named_proxy_dict [pr_dict_proxy_dict_proxy_dictプレフィックス] topo.stored_named_proxy_dict [プレフィックス] = P

def Run_Basic_MRT_for_All_Sources(topo): for src in topo.node_list: Reset_Computed_Node_and_Intf_Values(topo) Run_Basic_MRT_for_One_Source(topo,src) if src is topo.gadag_root: Store_GADAG_and_Named_Proxies_Once(topo)

def Run_Basic_MRT_for_All_Sources(topo):for src in topo.node_list:Reset_Computed_Node_and_Intf_Values(topo)Run_Basic_MRT_for_One_Source(topo、src)if src is topo.gadag_root:Store_GADAG_and_Named_Prod

def Run_MRT_for_One_Source(topo, src): MRT_Island_Identification(topo, src, 0, 0) Set_Island_Intf_and_Node_Lists(topo) Set_GADAG_Root(topo,src) Sort_Interfaces(topo) Run_Lowpoint(topo) Assign_Remaining_Lowpoint_Parents(topo) Construct_GADAG_via_Lowpoint(topo) Run_Assign_Block_ID(topo) Add_Undirected_Links(topo) Compute_MRT_NH_For_One_Src_To_Island_Dests(topo,src) Store_MRT_Nexthops_For_One_Src_To_Island_Dests(topo,src) Select_Alts_For_One_Src_To_Island_Dests(topo,src) Store_Primary_and_Alts_For_One_Src_To_Island_Dests(topo,src) Create_Basic_Named_Proxy_Nodes(topo) Attach_Named_Proxy_Nodes(topo) Compute_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src) Store_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src) Compute_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src) Store_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src) Select_Alts_For_One_Src_To_Named_Proxy_Nodes(topo,src) Store_Alts_For_One_Src_To_Named_Proxy_Nodes(topo,src)

DEF Run_MRT_for_One_Source(TOPO、SRC):MRT_Island_Identification(TOPO、SRC、0、0)Set_Island_Intf_and_Node_Lists(TOPO)Set_GADAG_Root(TOPO、SRC)Sort_Interfaces(TOPO)Run_Lowpoint(TOPO)Assign_Remaining_Lowpoint_Parents(TOPO)Construct_GADAG_via_Lowpoint(TOPO)Run_Assign_Block_ID(TOPO)Add_Undirected_Links( TOPO)Compute_MRT_NH_For_One_Src_To_Island_Dests(TOPO、SRC)Store_MRT_Nexthops_For_One_Src_To_Island_Dests(TOPO、SRC)Select_Alts_For_One_Src_To_Island_Dests(TOPO、SRC)Store_Primary_and_Alts_For_One_Src_To_Island_Dests(TOPO、SRC)Create_Basic_Named_Proxy_Nodes(TOPO)Attach_Named_Proxy_Nodes(TOPO)Compute_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(TOPO、SRC)Store_MRT_NHs_For_One_Src_To_Named_Proxy_Nodes(TOPO、SRC)Compute_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(TOPO、 src)Store_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo、src)Select_Alts_For_One_Src_To_Named_Proxy_Nodes(topo、src)Store_Alts_For_One_Src_To_Named_Proxy_Nodes(topo、src)

def Run_Prim_SPF_for_One_Source(topo,src): Normal_SPF(topo, src) Store_Primary_NHs_For_One_Source_To_Nodes(topo,src) Create_Basic_Named_Proxy_Nodes(topo) Compute_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src) Store_Primary_NHs_For_One_Src_To_Named_Proxy_Nodes(topo,src)

def Run_Prim_SPF_for_One_Source(topo、src):Normal_SPF(topo、src)Store_Primary_NHs_For_One_Source_To_Nodes(topo、src)Create_Basic_Named_Proxy_Nodes(topo)Compute_Primary_NHs_For_One_Src_TosNamerc_TosNamerc_Tosrc_Tosrc_Tos_rc_Tosrc_Tos_rc_Tos_rc_Tos_rc_Tos_rc_To_rc_Tos_rc_Tos_rc_Tos_rc_To_Name_Pro_To_Name

def Run_MRT_for_All_Sources(topo): for src in topo.node_list: Reset_Computed_Node_and_Intf_Values(topo) if src in topo.island_node_list_for_test_gr: # src runs MRT if it is in same MRT island as test_gr Run_MRT_for_One_Source(topo,src) if src is topo.gadag_root: Store_GADAG_and_Named_Proxies_Once(topo) else: # src still runs SPF if not in MRT island Run_Prim_SPF_for_One_Source(topo,src)

def Run_MRT_for_All_Sources(topo):for src in topo.node_list:Reset_Computed_Node_and_Intf_Values(topo)if src in topo.island_node_list_for_test_gr:#srcがMRTを実行しているのは、MRTアイランドがtest_grと同じである場合です。 Store_GADAG_and_Named_Proxies_Once(topo)else:#MRTアイランドにない場合でも、srcはSPFを実行しますRun_Prim_SPF_for_One_Source(topo、src)

def Write_Output_To_Files(topo,file_prefix): Write_GADAG_To_File(topo,file_prefix) Write_Both_MRTs_For_All_Dests_To_File(topo,file_prefix) Write_Alternates_For_All_Dests_To_File(topo,file_prefix)

def Write_Output_To_Files(topo、file_prefix):Write_GADAG_To_File(topo、file_prefix)Write_Both_MRTs_For_All_Dests_To_File(topo、file_prefix)Write_Alternates_For_All_Dests_To_File(topo、file_prefix)

def Create_Basic_Topology_Input_File(filename):
    data = [[01,02,10],[02,03,10],[03,04,11],[04,05,10,20],[05,06,10],
            [06,07,10],[06,07,10],[06,07,15],[07,01,10],[07,51,10],
            [51,52,10],[52,53,10],[53,03,10],[01,55,10],[55,06,10],
            [04,12,10],[12,13,10],[13,14,10],[14,15,10],[15,16,10],
            [16,17,10],[17,04,10],[05,76,10],[76,77,10],[77,78,10],
            [78,79,10],[79,77,10]]
    with open(filename + '.csv', 'w') as topo_file:
        for item in data:
            if len(item) > 3:
                line = (str(item[0])+','+str(item[1])+','+
                        str(item[2])+','+str(item[3])+'\n')
            else:
                line = (str(item[0])+','+str(item[1])+','+
                        str(item[2])+'\n')
            topo_file.write(line)
        
def Create_Complex_Topology_Input_File(filename):
    data = [[01,02,10],[02,03,10],[03,04,11],[04,05,10,20],[05,06,10],
            [06,07,10],[06,07,10],[06,07,15],[07,01,10],[07,51,10],
            [51,52,10],[52,53,10],[53,03,10],[01,55,10],[55,06,10],
            [04,12,10],[12,13,10],[13,14,10],[14,15,10],[15,16,10],
            [16,17,10],[17,04,10],[05,76,10],[76,77,10],[77,78,10],
            [78,79,10],[79,77,10]]
    with open(filename + '.csv', 'w') as topo_file:
        for item in data:
            if len(item) > 3:
                line = (str(item[0])+','+str(item[1])+','+
                        str(item[2])+','+str(item[3])+'\n')
            else:
                line = (str(item[0])+','+str(item[1])+','+
                        str(item[2])+'\n')
            topo_file.write(line)
        
    data = [[01,0],[02,0],[03,0],[04,0],[05,0],
            [06,0],[07,0],
            [51,0],[55,0],
            [12,0],[13,0],[14,0],[15,0],
            [16,0],[17,0],[76,0],[77,0],
            [78,0],[79,0]]
    with open(filename + '.profile', 'w') as topo_file:
        for item in data:
            line = (str(item[0])+','+str(item[1])+'\n')
            topo_file.write(line)
        
    data = [[2001,05,100],[2001,07,120],[2001,03,130],
            [2002,13,100],[2002,15,110],
            [2003,52,100],[2003,78,100]]
        
    with open(filename + '.prefix', 'w') as topo_file:
        for item in data:
            line = (str(item[0])+','+str(item[1])+','+
                    str(item[2])+'\n')
            topo_file.write(line)
        
def Generate_Basic_Topology_and_Run_MRT():
    this_gadag_root = 3
    Create_Basic_Topology_Input_File('basic_topo_input')
    topo = Create_Topology_From_File('basic_topo_input')
    res_file_base = 'basic_topo'
    Compute_Island_Node_List_For_Test_GR(topo, this_gadag_root)
    Raise_GADAG_Root_Selection_Priority(topo,this_gadag_root)
    Run_Basic_MRT_for_All_Sources(topo)
    Write_Output_To_Files(topo, res_file_base)
        
def Generate_Complex_Topology_and_Run_MRT():
    this_gadag_root = 3
    Create_Complex_Topology_Input_File('complex_topo_input')
    topo = Create_Topology_From_File('complex_topo_input')
    Add_Profile_IDs_from_File(topo,'complex_topo_input')
    Add_Prefix_Advertisements_From_File(topo,'complex_topo_input')
    Compute_Island_Node_List_For_Test_GR(topo, this_gadag_root)
    Add_Prefixes_for_Non_Island_Nodes(topo)
    res_file_base = 'complex_topo'
    Raise_GADAG_Root_Selection_Priority(topo,this_gadag_root)
    Run_MRT_for_All_Sources(topo)
    Write_Output_To_Files(topo, res_file_base)
        

Generate_Basic_Topology_and_Run_MRT()

Generate_Basic_Topology_and_Run_MRT()

Generate_Complex_Topology_and_Run_MRT()

Generate_Complex_Topology_and_Run_MRT()

<CODE ENDS>

<コード終了>

Appendix B. Constructing a GADAG Using SPFs
付録B. SPFを使用したGADAGの作成

The basic idea in this method for constructing a GADAG is to use slightly modified SPF computations to find ears. In every block, an SPF computation is first done to find a cycle from the local root and then SPF computations in that block find ears until there are no more interfaces to be explored. The used result from the SPF computation is the path of interfaces indicated by following the previous hops from the minimized IN_GADAG node back to the SPF root.

GADAGを作成するこの方法の基本的な考え方は、わずかに変更されたSPF計算を使用して耳を見つけることです。すべてのブロックで、最初にローカルルートからのサイクルを見つけるためにSPF計算が行われ、次にそのブロックでのSPF計算が探査対象のインターフェイスがなくなるまで耳を見つけます。 SPF計算の使用結果は、最小化されたIN_GADAGノードからSPFルートに戻る前のホップをたどることによって示されるインターフェイスのパスです。

To do this, first all cut-vertices must be identified and localroots assigned as specified in Figure 12.

これを行うには、最初にすべてのカット頂点を識別し、図12で指定されているようにローカルルートを割り当てる必要があります。

The slight modifications to the SPF are as follows. The root of the block is referred to as the block-root; it is either the GADAG root or a cut-vertex.

SPFのわずかな変更は次のとおりです。ブロックのルートは、ブロックルートと呼ばれます。 GADAGルートまたはカット頂点です。

a. The SPF is rooted at a neighbor x of an IN_GADAG node y. All links between y and x are marked as TEMP_UNUSABLE. They should not be used during the SPF computation.

a. SPFは、IN_GADAGノードyのネイバーxをルートとします。 yとxの間のすべてのリンクは、TEMP_UNUSABLEとしてマークされます。 SPFの計算中には使用しないでください。

b. If y is not the block-root, then it is marked TEMP_UNUSABLE. It should not be used during the SPF computation. This prevents ears from starting and ending at the same node and avoids cycles; the exception is because cycles to/from the block-root are acceptable and expected.

b. yがブロックルートでない場合は、TEMP_UNUSABLEとマークされます。 SPF計算中は使用しないでください。これにより、耳が同じノードで開始および終了することがなくなり、サイクルが回避されます。例外は、block-rootへの、またはblock-rootからのサイクルが許容され、予想されるためです。

c. Do not explore links to nodes whose localroot is not the block-root. This keeps the SPF confined to the particular block.

c. localrootがblock-rootではないノードへのリンクを探索しないでください。これにより、SPFが特定のブロックに限定されます。

d. Terminate when the first IN_GADAG node z is minimized.

d. 最初のIN_GADAGノードzが最小化されたときに終了します。

e. Respect the existing directions (e.g., INCOMING, OUTGOING, UNDIRECTED) already specified for each interface.

e. 各インターフェースにすでに指定されている既存の方向(INCOMING、OUTGOING、UNDIRECTEDなど)を尊重します。

Mod_SPF(spf_root, block_root) Initialize spf_heap to empty Initialize nodes' spf_metric to infinity spf_root.spf_metric = 0 insert(spf_heap, spf_root) found_in_gadag = false while (spf_heap is not empty) and (found_in_gadag is false) min_node = remove_lowest(spf_heap) if min_node.IN_GADAG found_in_gadag = true else foreach interface intf of min_node if ((intf.OUTGOING or intf.UNDIRECTED) and ((intf.remote_node.localroot is block_root) or (intf.remote_node is block_root)) and (intf.remote_node is not TEMP_UNUSABLE) and (intf is not TEMP_UNUSABLE)) path_metric = min_node.spf_metric + intf.metric if path_metric < intf.remote_node.spf_metric intf.remote_node.spf_metric = path_metric intf.remote_node.spf_prev_intf = intf insert_or_update(spf_heap, intf.remote_node) return min_node

Mod_SPF(spf_root、block_root)spf_heapを空に初期化するノードのspf_metricを無限大に初期化するspf_root.spf_metric = 0 insert(spf_heap、spf_root)found_in_gadag = false while(spf_heap is not empty)and(found_in_gadag is false)min_node = removeap_lowapest_lowapest_lowapest_lowap min_node.IN_GADAG found_in_gadag = true else foreachインターフェースintf of min_node if((intf.OUTGOING or intf.UNDIRECTED)and((intf.remote_node.localroot is block_root)or(intf.remote_node is block_root))and(intf.remote_node is not TEMP_UNUSABLE)および(intfはTEMP_UNUSABLEではありません))path_metric = min_node.spf_metric + intf.metric if path_metric <intf.remote_node.spf_metric intf.remote_node.spf_metric = path_metric intf.remote_node.spf_prev_intf_intf_intf_intf_intf_intf_intf_intf_inthe_insert min_node

SPF_for_Ear(cand_intf.local_node,cand_intf.remote_node, block_root, method) Mark all interfaces between cand_intf.remote_node and cand_intf.local_node as TEMP_UNUSABLE if cand_intf.local_node is not block_root Mark cand_intf.local_node as TEMP_UNUSABLE Initialize ear_list to empty end_ear = Mod_SPF(spf_root, block_root) y = end_ear.spf_prev_hop while y.local_node is not spf_root add_to_list_start(ear_list, y) y.local_node.IN_GADAG = true y = y.local_node.spf_prev_intf if(method is not hybrid) Set_Ear_Direction(ear_list, cand_intf.local_node, end_ear,block_root) Clear TEMP_UNUSABLE from all interfaces between cand_intf.remote_node and cand_intf.local_node Clear TEMP_UNUSABLE from cand_intf.local_node return end_ear

SPF_for_Ear(cand_intf.local_node、cand_intf.remote_node、block_root、method)cand_intf.local_nodeがblock_rootでない場合、cand_intf.remote_nodeとcand_intf.local_nodeの間のすべてのインターフェースをTEMP_UNUSABLEとしてマークしますcand_intf.local_nodeを初期化します。 block_root)y = end_ear.spf_prev_hop while y.local_node is spf_root add_to_list_start(ear_list、y)y.local_node.IN_GADAG = true y = y.local_node.spf_prev_intf if(method is hybrid)Set_Ear_Direction(ear_list、cand_int.cand_int 、block_root)cand_intf.remote_nodeとcand_intf.local_nodeの間のすべてのインターフェースからTEMP_UNUSABLEをクリアするcand_intf.local_nodeからTEMP_UNUSABLEをクリアする

Figure 31: Modified SPF for GADAG Construction

図31:GADAG構築用に変更されたSPF

Assume that an ear is found by going from y to x and then running an SPF that terminates by minimizing z (e.g., y<->x...q<->z). Now it is necessary to determine the direction of the ear; if y<<z, then the path should be y->x...q->z; but if y>>z, then the path should be y<-x...q<-z. In Section 5.5, the same problem was handled by finding all ears that started at a node before looking at ears starting at nodes higher in the partial order. In this GADAG construction method, using that approach could mean that new ears aren't added in order of their total cost since all ears connected to a node would need to be found before additional nodes could be found.

yからxに移動して、zを最小化することで終了するSPFを実行して耳が見つかると仮定します(たとえば、y <-> x ... q <-> z)。次に、耳の方向を決定する必要があります。 y << zの場合、パスはy-> x ... q-> zになります。ただし、y >> zの場合、パスはy <-x ... q <-zになります。セクション5.5では、ノードから始まるすべての耳を見つける前に、部分的な順序でより高いノードから始まる耳を調べることで、同じ問題が処理されました。このGADAG構築方法では、そのアプローチを使用すると、追加のノードを見つける前にノードに接続されているすべての耳を見つける必要があるため、新しい耳が総コストの順に追加されない可能性があります。

The alternative is to track the order relationship of each node with respect to every other node. This can be accomplished by maintaining two sets of nodes at each node. The first set, Higher_Nodes, contains all nodes that are known to be ordered above the node. The second set, Lower_Nodes, contains all nodes that are known to be ordered below the node. This is the approach used in this GADAG construction method.

別の方法は、他のすべてのノードに対する各ノードの順序関係を追跡することです。これは、各ノードで2セットのノードを維持することによって実現できます。最初のセットHigher_Nodesには、ノードの上に順序付けられることがわかっているすべてのノードが含まれています。 2番目のセットLower_Nodesには、ノードの下に順序付けられていることがわかっているすべてのノードが含まれています。これは、このGADAG構築メソッドで使用されるアプローチです。

      Set_Ear_Direction(ear_list, end_a, end_b, block_root)
        // Default of A_TO_B for the following cases:
        // (a) end_a and end_b are the same (root)
        // or (b) end_a is in end_b's Lower Nodes
        // or (c) end_a and end_b were unordered with respect to each
        //        other
        direction = A_TO_B
        if (end_b is block_root) and (end_a is not end_b)
           direction = B_TO_A
        else if end_a is in end_b.Higher_Nodes
           direction = B_TO_A
        if direction is B_TO_A
           foreach interface i in ear_list
               i.UNDIRECTED = false
               i.INCOMING = true
               i.remote_intf.UNDIRECTED = false
               i.remote_intf.OUTGOING = true
        else
           foreach interface i in ear_list
               i.UNDIRECTED = false
               i.OUTGOING = true
               i.remote_intf.UNDIRECTED = false
               i.remote_intf.INCOMING = true
         if end_a is end_b
            return
         // Next, update all nodes' Lower_Nodes and Higher_Nodes
         if (end_a is in end_b.Higher_Nodes)
            foreach node x where x.localroot is block_root
                if end_a is in x.Lower_Nodes
                   foreach interface i in ear_list
                      add i.remote_node to x.Lower_Nodes
                if end_b is in x.Higher_Nodes
                   foreach interface i in ear_list
                      add i.local_node to x.Higher_Nodes
          else
            foreach node x where x.localroot is block_root
                if end_b is in x.Lower_Nodes
                   foreach interface i in ear_list
                      add i.local_node to x.Lower_Nodes
                if end_a is in x.Higher_Nodes
                   foreach interface i in ear_list
                      add i.remote_node to x.Higher_Nodes
        

Figure 32: Algorithm to Assign Links of an Ear Direction

図32:耳の方向のリンクを割り当てるアルゴリズム

A goal of this GADAG construction method is to find the shortest cycles and ears. An ear is started by going to a neighbor x of an IN_GADAG node y. The path from x to an IN_GADAG node is minimal, since it is computed via SPF. Since a shortest path is made of shortest paths, to find the shortest ears requires reaching from the set of IN_GADAG nodes to the closest node that isn't IN_GADAG. Therefore, an ordered tree is maintained of interfaces that could be explored from the IN_GADAG nodes. The interfaces are ordered by their characteristics of metric, local loopback address, remote loopback address, and ifindex, based on the Interface_Compare function defined in Figure 14.

このGADAG構築方法の目標は、最短のサイクルと耳を見つけることです。耳は、IN_GADAGノードyのネイバーxに移動することによって開始されます。 SPFによって計算されるため、xからIN_GADAGノードへのパスは最小限です。最短パスは最短パスで構成されるため、最短の耳を見つけるには、IN_GADAGノードのセットから、IN_GADAGではない最も近いノードに到達する必要があります。したがって、IN_GADAGノードから探索できるインターフェースの順序付きツリーが維持されます。インターフェイスは、図14で定義されているInterface_Compare関数に基づいて、メトリック、ローカルループバックアドレス、リモートループバックアドレス、およびifindexの特性によって順序付けられます。

This GADAG construction method ignores interfaces picked from the ordered list that belong to the block root if the block in which the interface is present already has an ear that has been computed. This is necessary since we allow at most one incoming interface to a block root in each block. This requirement stems from the way next hops are computed as was seen in Section 5.7. After any ear gets computed, we traverse the newly added nodes to the GADAG and insert interfaces whose far end is not yet on the GADAG to the ordered tree for later processing.

このGADAG構築メソッドは、インターフェイスが存在するブロックにすでに計算済みのイヤーがある場合、ブロックルートに属する順序付きリストから選択されたインターフェイスを無視します。各ブロック内のブロックルートへの受信インターフェイスを最大1つ許可するため、これは必要です。この要件は、セクション5.7に見られるように、ネクストホップが計算される方法に由来します。耳が計算されたら、新しく追加されたノードをGADAGに移動し、遠端がまだGADAGにないインターフェイスを、後の処理のために順序付けられたツリーに挿入します。

Finally, cut-links are a special case because there is no point in doing an SPF on a block of two nodes. The algorithm identifies cut-links simply as links where both ends of the link are cut-vertices. Cut-links can simply be added to the GADAG with both OUTGOING and INCOMING specified on their interfaces.

最後に、2つのノードのブロックでSPFを実行しても意味がないため、カットリンクは特別なケースです。アルゴリズムは、カットリンクをリンクの両端がカット頂点であるリンクとして単純に識別します。カットリンクは、インターフェイスにOUTGOINGとINCOMINGの両方を指定するだけでGADAGに追加できます。

add_eligible_interfaces_of_node(ordered_intfs_tree,node) for each interface of node if intf.remote_node.IN_GADAG is false insert(intf,ordered_intfs_tree)

intf.remote_node.IN_GADAGがfalseの場合、ノードの各インターフェースのadd_eligible_interfaces_of_node(ordered_intfs_tree、node)add(intf、ordered_intfs_tree)

check_if_block_has_ear(x,block_id) block_has_ear = false for all interfaces of x if ( (intf.remote_node.block_id == block_id) && intf.remote_node.IN_GADAG ) block_has_ear = true return block_has_ear

check_if_block_has_ear(x、block_id)block_has_ear = false if((intf.remote_node.block_id == block_id)&& intf.remote_node.IN_GADAG)block_has_ear = true return block_has_ear

     Construct_GADAG_via_SPF(topology, root)
       Compute_Localroot (root,root)
       Assign_Block_ID(root,0)
       root.IN_GADAG = true
          add_eligible_interfaces_of_node(ordered_intfs_tree,root)
       while ordered_intfs_tree is not empty
          cand_intf = remove_lowest(ordered_intfs_tree)
          if cand_intf.remote_node.IN_GADAG is false
             if L(cand_intf.remote_node) == D(cand_intf.remote_node)
                // Special case for cut-links
                cand_intf.UNDIRECTED = false
                cand_intf.remote_intf.UNDIRECTED = false
                cand_intf.OUTGOING = true
                cand_intf.INCOMING = true
                cand_intf.remote_intf.OUTGOING = true
                cand_intf.remote_intf.INCOMING = true
                cand_intf.remote_node.IN_GADAG = true
             add_eligible_interfaces_of_node(
                            ordered_intfs_tree,cand_intf.remote_node)
          else
             if (cand_intf.remote_node.local_root ==
                 cand_intf.local_node) &&
                 check_if_block_has_ear(cand_intf.local_node,
                              cand_intf.remote_node.block_id))
                 /* Skip the interface since the block root
                 already has an incoming interface in the
                 block */
             else
             ear_end = SPF_for_Ear(cand_intf.local_node,
                     cand_intf.remote_node,
                     cand_intf.remote_node.localroot,
                     SPF method)
             y = ear_end.spf_prev_hop
             while y.local_node is not cand_intf.local_node
                 add_eligible_interfaces_of_node(
                     ordered_intfs_tree, y.local_node)
                 y = y.local_node.spf_prev_intf
        

Figure 33: SPF-Based Method for GADAG Construction

図33:GADAG構築のためのSPFベースの方法

Appendix C. Constructing a GADAG Using a Hybrid Method
付録C.ハイブリッド方式を使用したGADAGの作成

The idea of this method is to combine the salient features of the lowpoint inheritance and SPF methods. To this end, we process nodes as they get added to the GADAG just like in the lowpoint inheritance by maintaining a stack of nodes. This ensures that we do not need to maintain lower and higher sets at each node to ascertain ear directions since the ears will always be directed from the node being processed towards the end of the ear. To compute the ear however, we resort to an SPF to have the possibility of better ears (path lengths) thus giving more flexibility than the restricted use of lowpoint/dfs parents.

このメソッドのアイデアは、低点継承とSPFメソッドの顕著な特徴を組み合わせることです。このため、ノードのスタックを維持することにより、低ポイントの継承と同様に、ノードがGADAGに追加されるときにノードを処理します。これにより、耳は常に処理中のノードから耳の端に向けられるため、耳の方向を確認するために各ノードで上下のセットを維持する必要がなくなります。ただし、耳を計算するには、SPFを使用して耳(パスの長さ)を改善する可能性があるため、lowpoint / dfsペアレントの制限付きの使用よりも柔軟性が高くなります。

Regarding ears involving a block root, unlike the SPF method, which ignored interfaces of the block root after the first ear, in the hybrid method we would have to process all interfaces of the block root before moving on to other nodes in the block since the direction of an ear is predetermined. Thus, whenever the block already has an ear computed, and we are processing an interface of the block root, we mark the block root as unusable before the SPF run that computes the ear. This ensures that the SPF terminates at some node other than the block-root. This in turn guarantees that the block-root has only one incoming interface in each block, which is necessary for correctly computing the next hops on the GADAG.

最初の耳の後のブロックルートのインターフェイスを無視するSPFメソッドとは異なり、ブロックルートを含む耳については、ハイブリッドメソッドでは、ブロックルートの他のノードに移動する前にブロックルートのすべてのインターフェイスを処理する必要があります。耳の向きは決まっています。したがって、ブロックですでに耳が計算されていて、ブロックルートのインターフェイスを処理している場合は常に、耳を計算するSPF実行の前にブロックルートを使用不可としてマークします。これにより、SPFがブロックルート以外のノードで終了することが保証されます。これにより、block-rootには各ブロックで1つの着信インターフェイスのみが存在することが保証されます。これは、GADAGのネクストホップを正しく計算するために必要です。

As in the SPF GADAG, bridge ears are handled as a special case.

SPF GADAGと同様に、ブリッジイヤーは特別なケースとして処理されます。

The entire algorithm is shown below in Figure 34.

アルゴリズム全体を図34に示します。

find_spf_stack_ear(stack, x, y, xy_intf, block_root) if L(y) == D(y) // Special case for cut-links xy_intf.UNDIRECTED = false xy_intf.remote_intf.UNDIRECTED = false xy_intf.OUTGOING = true xy_intf.INCOMING = true xy_intf.remote_intf.OUTGOING = true xy_intf.remote_intf.INCOMING = true xy_intf.remote_node.IN_GADAG = true push y onto stack return else if (y.local_root == x) && check_if_block_has_ear(x,y.block_id) //Avoid the block root during the SPF Mark x as TEMP_UNUSABLE end_ear = SPF_for_Ear(x,y,block_root,hybrid) If x was set as TEMP_UNUSABLE, clear it cur = end_ear while (cur != y) intf = cur.spf_prev_hop prev = intf.local_node intf.UNDIRECTED = false intf.remote_intf.UNDIRECTED = false intf.OUTGOING = true intf.remote_intf.INCOMING = true push prev onto stack cur = prev xy_intf.UNDIRECTED = false xy_intf.remote_intf.UNDIRECTED = false xy_intf.OUTGOING = true xy_intf.remote_intf.INCOMING = true return

find_spf_stack_ear(stack、x、y、xy_intf、block_root)if L(y)== D(y)//カットリンクの特殊なケースxy_intf.UNDIRECTED = false xy_intf.remote_intf.UNDIRECTED = false xy_intf.OUTGOING = true xy_intf。 INCOMING = true xy_intf.remote_intf.OUTGOING = true xy_intf.remote_intf.INCOMING = true xy_intf.remote_node.IN_GADAG = true yをスタックにプッシュし、else if(y.local_root == x)&& check_if_block_has_ear(x、y.block_id)// SPF中にブロックルートを回避するxをTEMP_UNUSABLEとしてマークするend_ear = SPF_for_Ear(x、y、block_root、hybrid)xがTEMP_UNUSABLEとして設定されている場合、それを消去するcur = end_ear while(cur!= y)intf = cur.spf_prev_hop prev = intf .local_node intf.UNDIRECTED = false intf.remote_intf.UNDIRECTED = false intf.OUTGOING = true intf.remote_intf.INCOMING = true prevをスタックにプッシュするcur = prev xy_intf.UNDIRECTED = false xy_intf.remote_intf.UNDIRECTED = false xy_intf.OUT xy_intf.remote_intf.INCOMING = true return

Construct_GADAG_via_hybrid(topology,root) Compute_Localroot (root,root) Assign_Block_ID(root,0) root.IN_GADAG = true Initialize Stack to empty push root onto Stack while (Stack is not empty) x = pop(Stack) for each interface intf of x y = intf.remote_node if y.IN_GADAG is false find_spf_stack_ear(stack, x, y, intf, y.block_root)

Construct_GADAG_via_hybrid(topology、root)Compute_Localroot(root、root)Assign_Block_ID(root、0)root.IN_GADAG = trueスタックを初期化してスタックにルートをスタックにプッシュします(Stackは空ではありません)x = xyの各インターフェイスintfのpop(Stack) = intf.remote_node y.IN_GADAGがfalseの場合find_spf_stack_ear(stack、x、y、intf、y.block_root)

Figure 34: Hybrid GADAG Construction Method

図34:ハイブリッドGADAG構築方法

Acknowledgements

謝辞

The authors would like to thank Shraddha Hegde, Eric Wu, Janos Farkas, Stewart Bryant, Alvaro Retana, and Deccan (Shaofu Peng) for their suggestions and review. We would also like to thank Anil Kumar SN for his assistance in clarifying the algorithm description and pseudocode.

著者は、彼らの提案とレビューのために、Shraddha Hegde、Eric Wu、Janos Farkas、Stewart Bryant、Alvaro Retana、およびDeccan(Shaofu Peng)に感謝します。アルゴリズムの説明と疑似コードの明確化にご協力いただいたAnil Kumar SNにも感謝いたします。

Authors' Addresses

著者のアドレス

Gabor Sandor Enyedi Ericsson Konyves Kalman krt 11 Budapest 1097 Hungary

Gabor Sandor Enyedi Ericsson Konyves Kalman krt 11ブダペスト1097ハンガリー

   Email: Gabor.Sandor.Enyedi@ericsson.com
        

Andras Csaszar Ericsson Konyves Kalman krt 11 Budapest 1097 Hungary

Andras Csaszar Ericsson Konyves Kalman krt 11ブダペスト1097ハンガリー

   Email: Andras.Csaszar@ericsson.com
        

Alia Atlas Juniper Networks 10 Technology Park Drive Westford, MA 01886 United States

Alia Atlas Juniper Networks 10 Technology Park Drive Westford、MA 01886アメリカ合衆国

   Email: akatlas@juniper.net
        

Chris Bowers Juniper Networks 1194 N. Mathilda Ave. Sunnyvale, CA 94089 United States

Chris Bowers Juniper Networks 1194 N. Mathilda Ave. Sunnyvale、CA 94089アメリカ合衆国

   Email: cbowers@juniper.net
        

Abishek Gopalan University of Arizona 1230 E Speedway Blvd. Tucson, AZ 85721 United States

アリゾナのアビシェクゴパラン大学1230 Eスピードウェイブルバード。ツーソン、AZ 85721アメリカ合衆国

   Email: abishek@ece.arizona.edu