跳到主要内容

RFC 3031 - 标签分发规程(Label Distribution Procedures)

5. 标签分发规程(Hop-by-Hop)​

在本节中, 我们只考虑这样一些标签绑定 (label binding): 它们被用于「沿其逐跳路由路径 (hop-by-hop routed path) 进行标签交换的流量」. 在这些情形下, 所讨论的标签将对应于路由表中的某个地址前缀.

5.1 通告与使用标签的规程(The Procedures for Advertising and Using labels)​

有多种不同的规程可用于分发标签绑定. 其中一些由下游 LSR (downstream LSR) 执行, 另一些由上游 LSR (upstream LSR) 执行.

下游 LSR 必须执行:

  • 分发规程 (Distribution Procedure), 以及

  • 撤回规程 (Withdrawal Procedure).

上游 LSR 必须执行:

  • 请求规程 (Request Procedure), 以及

  • 不可用规程 (NotAvailable Procedure), 以及

  • 释放规程 (Release Procedure), 以及

  • 标签使用规程 (labelUse Procedure).

MPLS 体系结构为上述每一种规程都支持若干种变体.

然而, MPLS 体系结构并不支持所有变体的所有可能组合. 受支持的组合集合将在 5.2 节中描述, 该节还将讨论不同组合之间的互操作性.

5.1.1 下游 LSR: 分发规程(Downstream LSR: Distribution Procedure)​

分发规程由下游 LSR 用来确定: 何时应当把「某个特定地址前缀的标签绑定」分发给它的标签分发对等体 (label distribution peers). 体系结构支持四种不同的分发规程.

无论采用哪一种具体规程, 若某个特定地址前缀的标签绑定已由下游 LSR Rd 分发给上游 LSR Ru, 且该绑定的属性 (如上文所定义) 在任何时候发生变化, 则 Rd 必须把新属性告知 Ru.

若某个 LSR 维护着到达某特定地址前缀的多条路由, 那么, 该 LSR 是否为该地址前缀绑定多个标签 (每条路由一个), 从而分发多个绑定, 属于本地事务 (local matter).

5.1.1.1 PushUnconditional​

设 Rd 是一个 LSR. 假设:

  1. X 是 Rd 路由表中的一个地址前缀;

  2. 就 X 而言, Ru 是 Rd 的标签分发对等体.

只要这些条件成立, Rd 就必须为 X 绑定一个标签, 并把该绑定分发给 Ru. Rd 有责任记录它已分发给 Ru 的那些绑定, 并确保 Ru 始终持有这些绑定.

执行「下游自主标签分配」(unsolicited downstream label assignment)、且采用「独立 LSP 控制模式」(Independent LSP Control Mode) 的 LSR 会使用这一规程.

5.1.1.2 PushConditional​

设 Rd 是一个 LSR. 假设:

  1. X 是 Rd 路由表中的一个地址前缀;

  2. 就 X 而言, Ru 是 Rd 的标签分发对等体;

  3. Rd 是 X 的 LSP 出口 (LSP Egress) 或 LSP 代理出口 (LSP Proxy Egress), 或者 Rd 到 X 的第 3 层下一跳 (L3 next hop) 是 Rn, 其中 Rn 不同于 Ru, 且 Rn 已为 X 绑定标签并把该绑定分发给了 Rd.

那么, 一旦这些条件全部成立, Rd 就应当为 X 绑定一个标签, 并把该绑定分发给 Ru.

PushUnconditional 会为路由表中的所有地址前缀分发标签绑定, 而 PushConditional 只会为这样的地址前缀分发标签绑定: 或者已经从自己的 LSP 下一跳那里收到了标签绑定, 或者自己没有具备 MPLS 能力的 L3 下一跳.

执行下游自主标签分配、且采用「有序 LSP 控制模式」(Ordered LSP Control Mode) 的 LSR 会使用这一规程.

5.1.1.3 PulledUnconditional​

设 Rd 是一个 LSR. 假设:

  1. X 是 Rd 路由表中的一个地址前缀;

  2. 就 X 而言, Ru 是 Rd 的标签分发对等体;

  3. Ru 已显式请求 Rd 为 X 绑定一个标签, 并把该绑定分发给 Ru.

那么, Rd 应当为 X 绑定一个标签, 并把该绑定分发给 Ru. 注意: 若 X 不在 Rd 的路由表中, 或者就 X 而言 Rd 并不是 Ru 的标签分发对等体, 则 Rd 必须告知 Ru 它目前无法提供绑定.

若 Rd 已经把地址前缀 X 的一个绑定分发给了 Ru, 而又收到 Ru 对地址前缀 X 绑定的新请求, 则它会再绑定第二个标签, 并把新的绑定分发给 Ru. 第一个标签绑定仍然保持有效.

执行「下游按需标签分发」(downstream-on-demand label distribution)、且采用独立 LSP 控制模式的 LSR 会使用这一规程.

5.1.1.4 PulledConditional​

设 Rd 是一个 LSR. 假设:

  1. X 是 Rd 路由表中的一个地址前缀;

  2. 就 X 而言, Ru 是 Rd 的标签分发对等体;

  3. Ru 已显式请求 Rd 为 X 绑定一个标签, 并把该绑定分发给 Ru;

  4. Rd 是 X 的 LSP 出口或 LSP 代理出口, 或者 Rd 到 X 的 L3 下一跳是 Rn, 其中 Rn 不同于 Ru, 且 Rn 已为 X 绑定标签并把该绑定分发给了 Rd.

那么, 一旦这些条件全部成立, Rd 就应当为 X 绑定一个标签, 并把该绑定分发给 Ru. 注意: 若 X 不在 Rd 的路由表中, 且无法经由 Rd 到 X 的下一跳获得 X 的绑定, 或者就 X 而言 Rd 并不是 Ru 的标签分发对等体, 则 Rd 必须告知 Ru 它目前无法提供绑定.

然而, 若唯一未成立的条件是 Rn 尚未向 Rd 提供标签, 则 Rd 必须推迟对 Ru 的任何响应, 直到它从 Rn 收到绑定为止.

若 Rd 已经把地址前缀 X 的标签绑定分发给了 Ru, 而在此后的某个时刻该标签绑定的任何属性发生了变化, 则 Rd 必须把带有新属性的标签绑定重新分发给 Ru. 即使 Ru 没有发出新的请求, 它也必须这样做.

执行下游按需标签分配、且采用有序 LSP 控制模式的 LSR 会使用这一规程.

在 5.2 节中, 我们将讨论如何在任一给定时刻选择所要使用的具体规程, 以及如何确保选择了不同规程的 LSR 之间的互操作性.

5.1.2 上游 LSR: 请求规程(Upstream LSR: Request Procedure)​

请求规程由某地址前缀的上游 LSR 用来确定: 何时显式请求下游 LSR 为该前缀绑定标签并分发该绑定. 有三种可以采用的规程.

5.1.2.1 RequestNever​

从不发出请求. 若下游 LSR 使用的是 PushConditional 规程或 PushUnconditional 规程, 这一做法是有用的; 但若下游 LSR 使用的是 PulledUnconditional 规程或 PulledConditional 规程, 这一做法便没有用处.

当同时采用下游自主标签分发与「自由标签保留模式」(Liberal Label Retention Mode) 时, LSR 会使用这一规程.

5.1.2.2 RequestWhenNeeded​

只要到某地址前缀的 L3 下一跳发生了变化, 或者学到了新的地址前缀, 而自己又尚未从该下一跳那里获得针对该地址前缀的标签绑定, 就发出请求.

只要使用了「保守标签保留模式」(Conservative Label Retention Mode), LSR 就会使用这一规程.

5.1.2.3 RequestOnRequest​

除了按需发出请求 (如 5.1.2.2 节所述) 之外, 每当收到一个请求, 就再发出一个请求. 若 Ru 不具备充当 LSP 入口 (LSP ingress) 的能力, 它可以只在收到来自上游的请求时才发出请求.

若 Rd 收到 Ru 发来的这种请求, 且所针对的是 Rd 已经分发给 Ru 一个标签的地址前缀, 则 Rd 必须分配一个新的 (互不相同的) 标签, 把它绑定到 X, 并分发该绑定. (Rd 能否立即把该绑定分发给 Ru, 取决于所使用的分发规程.)

执行下游按需标签分发、但不做标签合并 (label merging) 的 LSR 会使用这一规程, 例如不支持 VC 合并 (VC merge) 的 ATM-LSR.

5.1.3 上游 LSR: 不可用规程(Upstream LSR: NotAvailable Procedure)​

若 Ru 与 Rd 分别是地址前缀 X 的上游与下游标签分发对等体, Rd 是 Ru 到 X 的 L3 下一跳, 且 Ru 向 Rd 请求 X 的绑定, 但 Rd 答复说它目前无法提供绑定, 原因是它没有到 X 的下一跳, 那么, NotAvailable 规程决定了 Ru 如何应对. 有两种可能约束 Ru 行为的规程:

5.1.3.1 RequestRetry​

Ru 应当在稍后的时间再次发出请求. 也就是说, 请求方有责任在稍后重试, 以获得所需的绑定. 当使用下游按需标签分发时, 会采用这一规程.

5.1.3.2 RequestNoRetry​

Ru 绝不应当再次发出该请求, 而是假定 Rd 会在绑定可用时自动提供绑定. 若 Rd 使用的是 PushUnconditional 规程或 PushConditional 规程, 即若使用了下游自主标签分发, 这一做法是有用的.

注意: 若 Rd 答复 Ru 说它无法提供绑定的原因是出现了某种错误状态, 而不是因为它没有下一跳, 那么, Ru 的行为将由标签分发协议的错误恢复条件来约束, 而不是由 NotAvailable 规程来约束.

5.1.4 上游 LSR: 释放规程(Upstream LSR: Release Procedure)​

假设 Rd 是一个 LSR, 它已把某个标签绑定到地址前缀 X, 并已把该绑定分发给 LSR Ru. 若 Rd 恰好不是 Ru 到地址前缀 X 的 L3 下一跳, 或者已不再是 Ru 到地址前缀 X 的 L3 下一跳, 那么 Ru 将不会使用该标签. 释放规程决定了 Ru 在这种情形下如何行动. 有两种可能约束 Ru 行为的规程:

5.1.4.1 ReleaseOnChange​

Ru 应当释放该绑定, 并把自己已经这样做的情况告知 Rd. 这一规程用于实现保守标签保留模式.

5.1.4.2 NoReleaseOnChange​

Ru 应当维护该绑定, 以便在 Rd 日后重新成为 Ru 到 X 的 L3 下一跳时, 它能够立即再次使用该绑定. 这一规程用于实现自由标签保留模式.

5.1.5 上游 LSR: 标签使用规程(Upstream LSR: labelUse Procedure)​

假设 Ru 是一个 LSR, 它从 LSR Rd 那里收到了「标签 L 绑定到地址前缀 X」的绑定, 且就 X 而言 Ru 位于 Rd 的上游, 而且事实上 Rd 就是 Ru 到 X 的 L3 下一跳.

若 Rd 是 Ru 到 X 的 L3 下一跳, Ru 就会使用该绑定. 若在 Ru 收到该绑定的那一刻, Rd 不是 Ru 到 X 的 L3 下一跳, 则 Ru 此时不会对该绑定作任何使用. 不过, 若 Rd 日后成为 Ru 到 X 的 L3 下一跳, Ru 可以在稍后的某个时刻开始使用该绑定.

标签使用规程 (labelUse Procedure) 决定的正是 Ru 如何使用 Rd 的绑定.

Ru 可以使用两种规程:

5.1.5.1 UseImmediate​

Ru 可以立即把该绑定投入使用. 只要在任一时刻 Ru 持有来自 Rd 的 X 的绑定, 且 Rd 是 Ru 到 X 的 L3 下一跳, 那么 Rd 同时也会是 Ru 到 X 的 LSP 下一跳. 不使用「环路检测」(loop detection) 时采用这一规程.

5.1.5.2 UseIfLoopNotDetected​

这一规程与 UseImmediate 相同, 除非 Ru 已经在 LSP 中检测到环路 (loop). 若已检测到环路, Ru 将停止使用标签 L 向 Rd 转发分组.

使用环路检测时采用这一规程.

这种状态会一直持续下去, 直到 X 的下一跳发生变化, 或者环路不再被检测到为止.

5.1.6 下游 LSR: 撤回规程(Downstream LSR: Withdraw Procedure)​

在这种情形下, 只存在单一的规程.

当 LSR Rd 决定解除标签 L 与地址前缀 X 之间的绑定时, 必须把这次解除绑定 (unbinding) 的情况分发给该绑定曾被分发给的所有 LSR.

必须做到: 在 Rd 把「标签 L 绑定到任何其他地址前缀 Y (其中 X != Y)」的任何新绑定分发给某个 LSR Ru 之前, 先把「L 与 X 解除绑定」这件事分发给 Ru. 若 Ru 在得知 L 与 X 解除绑定之前就得知了 L 与 Y 之间的新绑定, 并且匹配 X 的分组和匹配 Y 的分组都会由 Ru 转发给 Rd, 那么, 在一段时期内, Ru 会既给匹配 X 的分组、又给匹配 Y 的分组打上标签 L.

标签绑定的分发与撤回 (withdrawal) 是通过标签分发协议 (label distribution protocol) 完成的. 所有标签分发协议都要求: 在两个标签分发对等体之间建立一个标签分发邻接 (label distribution adjacency) (「隐式对等体」(implicit peers) 除外). 若 LSR R1 与 LSR R2 之间存在标签分发邻接, 并且 R1 已经由该邻接从 LSR R2 收到了标签绑定, 那么, 若该邻接被任何一方拆除 (无论是由于故障, 还是作为正常操作的一部分), 经由该邻接收到的所有绑定都必须被视为已被撤回.

只要相关的标签分发邻接仍然存在, 被撤回的标签绑定就必须始终被显式地撤回. 若有第二个标签被绑定到某个地址前缀, 其结果并不是隐式地撤回第一个标签, 而是同时绑定这两个标签; 这是支持多路径路由 (multi-path routing) 所必需的. 若有第二个地址前缀被绑定到某个标签上, 其结果并不是隐式地撤回该标签与第一个地址前缀之间的绑定, 而是把该标签同时用于这两个地址前缀.

5.2 MPLS 方案: 受支持的规程组合(MPLS Schemes: Supported Combinations of Procedures)​

考虑两个 LSR, Ru 与 Rd, 就某个地址前缀集合而言它们是标签分发对等体, 其中 Ru 是上游对等体, Rd 是下游对等体.

约束 Ru 与 Rd 之间交互的 MPLS 方案 (MPLS scheme) 可以描述为一个五元组: <分发规程 (Distribution Procedure), 请求规程 (Request Procedure), 不可用规程 (NotAvailable Procedure), 释放规程 (Release Procedure), 标签使用规程 (labelUse Procedure)>. (由于只存在一种撤回规程, 无需提及.) 出现在某个位置上的 "*" 是通配符 (wild-card), 表示该类别中的任何规程都可以出现; 出现在特定位置上的 "N/A" 表示该类别中不需要任何规程.

只有下文规定的那些 MPLS 方案才得到 MPLS 体系结构的支持. 将来若证明了对其他方案的需要, 也可以增补.

5.2.1 支持标签合并的 LSR 的方案(Schemes for LSRs that Support Label Merging)​

若 Ru 与 Rd 是标签分发对等体, 且两者都支持标签合并, 则必须使用下列方案之一:

  1. <PushUnconditional, RequestNever, N/A, NoReleaseOnChange, UseImmediate>

    这是下游自主标签分发, 采用独立控制、自由标签保留模式, 且无环路检测.

  2. <PushUnconditional, RequestNever, N/A, NoReleaseOnChange, UseIfLoopNotDetected>

    这是下游自主标签分发, 采用独立控制、自由标签保留模式, 且带环路检测.

  3. <PushConditional, RequestWhenNeeded, RequestNoRetry, ReleaseOnChange, *>

    这是下游自主标签分发, 采用有序控制 (自出口发起) 与保守标签保留模式. 环路检测是可选的.

  4. <PushConditional, RequestNever, N/A, NoReleaseOnChange, *>

    这是下游自主标签分发, 采用有序控制 (自出口发起) 与自由标签保留模式. 环路检测是可选的.

  5. <PulledConditional, RequestWhenNeeded, RequestRetry, ReleaseOnChange, *>

    这是下游按需标签分发, 采用有序控制 (自入口发起)、保守标签保留模式, 环路检测可选.

  6. <PulledUnconditional, RequestWhenNeeded, N/A, ReleaseOnChange, UseImmediate>

    这是下游按需标签分发, 采用独立控制与保守标签保留模式, 不带环路检测.

  7. <PulledUnconditional, RequestWhenNeeded, N/A, ReleaseOnChange, UseIfLoopNotDetected>

    这是下游按需标签分发, 采用独立控制与保守标签保留模式, 带环路检测.

5.2.2 不支持标签合并的 LSR 的方案(Schemes for LSRs that do not Support Label Merging)​

假设 R1, R2, R3 和 R4 是一些不支持标签合并、但被用作 LSR 的 ATM 交换机. 再假设地址前缀 X 的 L3 逐跳路径是 <R1, R2, R3, R4>, 且目的地址为 X 的分组可以从其中任何一个 LSR 进入网络. 由于不存在多点到点 (multipoint-to-point) 能力, 这些 LSP 必须被实现为点到点 VC, 这意味着地址前缀 X 需要三条这样的 VC: <R1, R2, R3, R4>, <R2, R3, R4> 和 <R3, R4>.

因此, 若 R1 与 R2 是 MPLS 对等体, 且其中一方是使用传统 ATM 交换硬件 (即不具备信元交错抑制 (cell interleave suppression) 能力) 实现的 LSR, 或者在其他方面不具备执行标签合并的能力, 那么, R1 与 R2 之间使用的 MPLS 方案必须是下列之一:

  1. <PulledConditional, RequestOnRequest, RequestRetry, ReleaseOnChange, *>

    这是下游按需标签分发, 采用有序控制 (自入口发起)、保守标签保留模式, 环路检测可选.

    RequestOnRequest 规程的使用会导致 R4 为 X 向 R3 分发三个标签; R3 会为 X 向 R2 分发两个标签, 而 R2 会为 X 向 R1 分发一个标签.

  2. <PulledUnconditional, RequestOnRequest, N/A, ReleaseOnChange, UseImmediate>

    这是下游按需标签分发, 采用独立控制与保守标签保留模式, 不带环路检测.

  3. <PulledUnconditional, RequestOnRequest, N/A, ReleaseOnChange, UseIfLoopNotDetected>

    这是下游按需标签分发, 采用独立控制与保守标签保留模式, 带环路检测.

5.2.3 互操作性考虑(Interoperability Considerations)​

很容易看出, 某些五元组并不能产生可行的 MPLS 方案. 例如:

  • <PulledUnconditional, RequestNever, *, *, *> <PulledConditional, RequestNever, *, *, *>

    在这些 MPLS 方案中, 下游 LSR Rd 只有在收到上游 LSR Ru 的请求时才会分发标签绑定, 但 Ru 从不发出任何这样的请求. 显然, 这些方案是不可行的, 因为它们不会使标签绑定得到正确的分发.

  • <*, RequestNever, *, *, ReleaseOnChange>

    在这些 MPLS 方案中, Rd 在自己不使用绑定时就释放它们, 但它从不再次请求这些绑定, 即使它日后需要它们. 因此, 这些方案无法确保标签绑定得到正确的分发.

在本节中, 我们规定一些规则, 以防止一对标签分发对等体采用那些会导致不可行的 MPLS 方案的规程. 这些规则要求: 或者在标签分发邻接初始化期间, 在标签分发对等体之间交换信息; 或者以先验 (a priori) 的方式获知该信息 (即通过本文档范围之外的某种手段获得).

  1. 双方都必须声明自己是否支持标签合并.

  2. 若 Rd 不支持标签合并, Rd 必须在 PulledUnconditional 规程与 PulledConditional 规程之间作出选择. 若 Rd 选择了 PulledConditional, 则 Ru 被迫使用 RequestRetry 规程.

    也就是说, 若下游 LSR 不支持标签合并, 那么, 在选择 MPLS 方案时以它的偏好为准.

  3. 若 Ru 不支持标签合并而 Rd 支持, 则 Ru 必须在 RequestRetry 与 RequestNoRetry 两种规程之间作出选择. 这会分别迫使 Rd 使用 PulledConditional 规程或 PulledUnconditional 规程.

    也就是说, 若只有一方 LSR 不支持标签合并, 那么, 在选择 MPLS 方案时以它的偏好为准.

  4. 若 Ru 与 Rd 都支持标签合并, 那么, 自由与保守标签保留模式之间的选择权属于 Ru. 也就是说, Ru 既可以选择使用 RequestWhenNeeded/ReleaseOnChange (保守), 也可以选择使用 RequestNever/NoReleaseOnChange (自由). 然而, "push" 与 "pull" 之间、以及 "conditional" 与 "unconditional" 之间的选择权属于 Rd. 若 Ru 选择了自由标签保留模式, Rd 可以选择 PushUnconditional 或 PushConditional. 若 Ru 选择了保守标签保留模式, Rd 可以选择 PushConditional, PulledConditional 或 PulledUnconditional.

    这些选择共同决定了所使用的 MPLS 方案.