VLL技术简介
文/朱皓
1 什么是VLL技术
VLL(Virtual Leased Line),虚拟租用线路,是相对于专有租用线路而言(dedicated leased line),相对于专有租用线路中客户对线路的独占,VLL允许多个客户共享线路,通过VC(Virtual Circuit)区分客户数据,为不同客户提供逻辑上的专用通道,传统的ATM、FR技术均可以提供这种服务, Ethernet通过QinQ也可以提供类似服务。
VLL作为一种点到点的虚拟专线技术,被运营商广泛应用,用于为客户提供L2VPN服务。不过,不同的客户,采用的二层技术不尽相同,网络技术的发展和变更,使得ATM、FR、Ethernet等技术都被各种客户广泛采用,这对为这些客户提供服务的运营商来说,构成了一个挑战:如何在一个统一的基础网络架构上方便的为使用不同二层技术的客户提供L2VPN服务,以最大限度的降低运营开支?
MPLS技术的出现,使得运营商得以很好的应对这一挑战。采用MPLS最新技术,运营商在统一的MPLS/IP基础网络架构上,不但可以为客户提供L3VPN服务,也可以同时为客户提供L2VPN服务,使客户跨过运营商网络实现ATM、FR、HDLC、PPP、以太网等各种二层网络的互连。
MPLS目前提供两种L2VPN服务:
l Virtual Private LAN Service (VPLS):虚拟私有LAN服务,即在MPLS/IP网络中提供二层LAN服务,允许标准的以太设备通过MPLS/IP网络相连,就像连接在一个二层交换机上。
l Virtual Private Wire Service (VPWS):虚拟私有线路服务,即在MPLS/IP网络中模拟点到点二层服务,客户的二层设备跨过MPLS/IP核心网络相连,就像通过一根二层线路相连。
在纯IP网络中提供L2VPN服务,可以通过L2TPv3协议来实现,本文不涉及,有兴趣的读者可以查看IETF的L2TPEXT、L2VPN和PWE3 三个工作组的相关工作文档。
事实上,VPWS服务,和本文开篇提到的VLL是同一个东西,都是实现点到点的虚拟线路,本文要介绍的就是如何在统一的MPLS/IP基础网络架构中提供适应各种不同二层技术的VLL服务。
MPLS提供VLL服务的基本原理如下:运营商网络中,为客户的每一个点到点二层连接分配不同的VC标签,一对VC标签模拟一条虚拟线路,其中,VC标签的分配可以是静态配置,也可以是通过LDP、BGP等信令协议动态分配;客户二层数据帧在PE设备上被打上VC标签,然后在运营商核心网中转发到目的PE,在转发到目的PE时,如果使用MPLS隧道,根据实现和应用方式的不同,可能需要再加上一层或多层外层标签,也可以不使用MPLS隧道,比如Martini方式中就可以使用PE到目的PE的GRE隧道;报文到达目的PE后,剥掉外层隧道封装和VC标签,还原成最初的二层帧,发送给客户;报文在运营商网络中的标签转发过程,在对客户来说是透明的,客户分布在不同地域的二层设备,感觉就象是二层链路直连。
本文主要是介绍在路由器设备上的VLL技术,作为一种虚拟租用线路的实现方法,主要是在接入层和汇聚层使用。首先需要明确的一点是:VLL技术是一种点到点的虚拟专线技术,能够支持几乎所有的链路层协议。为了实现点到多点的MPLS L2VPN虚拟专线,目前的实现是VPLS(Virtual Private LAN Service)。VPLS技术不在本文中讨论。
VLL技术是建立在MPLS技术下的二层隧道技术。传统的二层隧道是通过对应的二层交换设备进行接续,来完成用户节点间二层隧道的建立。因为使用了不同的二层协议,因此不同种L2网络是隔离的。MPLS标签技术解决了统一兼容二层交换网络的问题。我们知道MPLS核心(下文称为SP网络)是根据标签进行交换的,其实可以把MPLS理解成为一个特殊的二层协议,也就是说在原有的各种L2封装外层加装MPLS封装。VLL技术的好处是显而易见的,第一是同一个SP网络可以提供多种二层协议的接续和交换,另一方面也为不同的L2交换网络互连提供了可能性。
因为VLL是MPLS技术的产物,因此类似于MPLS L3VPN的结构,使用内层标签来标识不同的虚拟线路(也就是二层隧道,下文延用传统的VC来表示Virtual Circuit),使用外层标签来做公共隧道。SP网络的设备不需要维护任何二层信息,只根据MPLS标签信息在公网隧道上进行MPLS转发。不同于L3VPN的是FEC(Forwarding Equivalence Class)的概念,在L3VPN中FEC实际上就是路由信息,而VLL中FEC是一些二层信息和VC标志等。
2 VLL技术细节
目前H3C的COMWARE平台全面支持VLL技术,实现方式分为4种:CCC、SVC、Martini、Kompella。
支持的链路层协议包括:ATM AAL5、FR、cisco HDLC、PPP、Ethernet(包括tag & untag两种方式)。
2.1 VLL技术的CCC方式
CCC方式最早是在什么时间提出,由谁在什么情况下提出是有一些争论的。一种说法是1998年提出,为解决ATM网络穿越MPLS的问题,后来这个技术得到不断的发展,可以支持大多数的链路层协议。当前的CCC实现虽然并没有标准,但基本的思路是类似的。有兴趣的读者可以研究一下 draft-kompella-ccc-02这个草案的状态是Dead,里面关于历史部分的说法不一定准确,大家可以关注一下技术实现的部分。
CCC(Circuit Cross Connect)方式是一种静态配置VC连接的方式,根据配置把VC端点收到的报文映射到一个静态的LSP隧道上去,这样二层报文在途经的每一跳设备上根据该静态LSP进行MPLS转发,最后将报文转发到VC的另一端。显然CCC的方式并不需要多层标签,只是一层MPLS标签而已,这一层标签在每个LSR上进行标签交换。CCC方式只需要SP网络支持MPLS转发就可以了。CCC对LSP隧道是独占的,而且在两个方向都需要配置静态的LSP。CCC支持本地连接模式,可以在同一个PE上的两个CE设备间建立CCC连接,也就是通过一个二层转发表项实现CE间的二层互连。CCC方式的L2交换模式与策略路由很相似,在策略路由中也是一跳一跳根据策略路由转发,策略路由是优先于路由表查找的。CCC方式逐跳建立静态的LSP,然后将L2报文在这条LSP上进行传递。
CCC用于小型,拓扑简单的MPLS网络,需要管理员手工配置。因为不需要其它交互信息的信令协议,因此消耗资源比较小,易于理解,但维护比较麻烦。
2.1.1 CCC的结构
图1 CCC可以支持的拓扑模型
CE1需要为两条CCC连接各准备一个接口(支持子接口),从CE的角度认为CE间是直连的。
同样的PE1侧也要有两个接口与CE1连接,第三个接口与CE2连接。
2.1.2 CCC的报文交互过程
图2 CCC的报文交换过程
CE1发送报文到CE3:(反方向过程相同)
PE1收到CE1相关接口送达的二层报文后,根据CCC的关联配置查找静态LSP,得到下一跳为PE2,标签为100。于是PE1在二层报文外封装MPLS头,lable=100并发送到连接PE2的接口。
PE2收到报文后查找LSP表,进行弹出操作,根据CCC的关联配置得到对应的出接口,于是将二层报文直接送到目的CE。
从这个过程中,我们可以看到,PE只关心报文是从那个接口收到的,如果这个接口关联到了某一个CCC连接,就去查找CCC的相关配置,并且进行MPLS封装和MPLS转发。因此PE连接CE侧的接口其实并不做任何二层的处理。同样在出接口的时候,PE只是解封装MPLS,并直接将报文送达到出接口。因此PE侧的CCC连接一旦建立起来后,PE连接CE接口的二层协议状态处于实质上down的状态。这一点在所有形式的VLL实现上都是相同的(当然,VLL在实现上可以在报文进入的PE侧进行二层报文头的解封装,并且在另一侧PE发向CE时进行重新封装,这样就可以实现二层协议的相互转换)。
CE1发送报文到CE2:
PE1收到CE1相关接口送达的二层报文后,根据CCC的关联配置发现是一个本地连接,直接得到出接口,然后不做任何处理,将二层报文通过出接口发送到CE2。
2.2 VLL技术的Martini方式
在VLL技术中,有两种重要的实现方法,使用了不同的信令协议来交互VC信息。这两种技术以协议草案的撰写者来命名,其中一种就是Martini方式。协议文档包括:
RFC4905 Encapsulation Methods for Transport of Layer 2 Frames over MPLS Networks
RFC4906 Transport of Layer 2 Frames Over MPLS
Martini方式使用标准的两层标签,内层标签是采用扩展的LDP作为信令进行交互。在Martini协议中对标准的LDP进行了扩展,增加了VC FEC的FEC类型用于VC标签的交换。它采用VC TYPE + VC ID来识别一个VC。VC TYPE表明链路层封装的类型,VC ID则用于唯一标识一个VC。同一个VC TYPE的所有VC中,其VC ID必须在整个PE中唯一。连接两个CE的PE通过LDP交换VC标签,并通过VC ID将对应的CE绑定起来,一个VC就建立起来了,两个CE通过这个VC来传递二层数据。
Martini方式没有提供象CCC方式的本地交换功能。外层标签用于将各个VC的数据在SP网络中进行传递,因为通过内层的VC标签可以对数据进行区分,因此外层隧道是可以被多个VC共享的。既然外层隧道是用于VC数据穿越SP网络,那么外层隧道当然也可以使用IP隧道封装,比如使用GRE隧道。
Martini方式适合稀疏的二层连接,例如星型连接。部署Martini方式需要SP网络能够自动的建立LSP隧道,所以需要SP网络支持MPLS转发及MPLS LDP,如果SP网络不支持LDP,那么可以使用GRE隧道封装。
2.2.1 Martini方式的结构
图3 Martini可以支持的拓扑模型
2.2.2 Martini的报文交互过程
图4 Martini的报文交互过程
CE1发送报文到CE3:(橙色部分,反方向过程相同)
PE1收到CE1相关接口送达的二层报文后,根据VC的关联配置查找VC-ID对应的表项,得到下一跳为PE2,VC标签为1025。于是PE1在二层报文外封装MPLS头,lable=1025。根据下一跳为PE2查找LSP隧道,得到外层标签为11,增加第二个MPLS封装lable=11,并发送到P。
P设备进行MPLS转发,查找LSP表后知道自己是次末中继,弹出外层标签,并发送到PE2
PE2收到报文后根据标签1025查找VC-ID对应的表项,得到出接口,将内层标签进行弹出操作,然后将二层报文直接送到目的CE3。
CE2发送报文到CE3的过程是类似的。从上面的交互过程中,我们可以看到,外层的LSP隧道是被共享的。PE2收到报文后会根据内层标签的不同映射到不同的VC上。
2.2.3 VC标签的交互信令
前面已经提到过Martini方式对传统的LDP做了扩展(LDP的标准协议文档为RFC3036),用于交互VC的信息,也就是传递VC标签,用于报文的发送。
首先Martini方式需要在PE间建立扩展的远程LDP会话,然后通过会话来交互VC信息。为了交互VC信息,增加了新的FEC的定义,新的FEC类型为128。下面是VC FEC结构。
图5 128类VC FEC结构
Martini方式通过VC Type + VC ID来区分不同的VC,在Interface parameters部分描述了与CE连接的接口以及MTU等其它一些信息。
在LDP会话中VC FEC出现在标签映射消息中,下图是一个标签映射消息的结构。
图6 LDP的标签映射消息
2.3 VLL技术的SVC方式
SVC方式是Martini方式的一种静态实现。在Martini中LDP是用于进行VC标签的交互,既然如此,是否可以不用LDP,在PE上直接根据VC ID来手动分配内层标签呢?当然是可以的,这就是SVC的模式,SVC是Martini的简化。公网隧道建立的方法与Martini相同,内层标签在配置VC的时候做好指定,这样就不需要使用VC标签的传递信令了。
所以SVC的网络拓扑模型与报文交互过程与Martini完全相同。
2.4 VLL技术的Kompella方式
Kompella是另一种VLL技术的主流模式,目前的协议文档是
RFC6624 Layer 2 Virtual Private Networks Using BGP for Auto-Discovery and Signaling
Kompella方式的L2 VPN与MPLS L3 VPN很相似,是使用BGP作为交换信令的。与MPLS L3 VPN类似,各个PE之间通过建立BGP会话自动发现L2 VPN的各个节点,并传递VPN信息,使用vpn-target来区分不同的VPN,这使得VPN组网具备了极大的灵活性。与Martini完全不同的是这里出现了真正VPN的概念,在不同的VPN内,CE ID是可以相同的。在内层标签的分配上,Kompella方式与Martini方式完全不同。Kompella采取标签块的方式,事先为每个CE分配一个标签块,这个标签块的的大小决定了这个CE可以与其它CE建立多少个连接。这样做的好处是允许为VPN分配一些额外的标签,留待以后扩容使用。PE根据这些标签块进行计算,得到实际的内层标签,用于报文的传输。
无论是使用Kompella方式还是Martini方式,二层报文传递时的MPLS封装是完全相同的,都是二层标签。另外,Kompella支持本地连接。
2.4.1 Kompella方式的结构
图7 Kompella可以支持的拓扑模型
Kompella方式对各种复杂的拓扑支持能力更好,这得益于BGP的节点自动发现能力。
2.4.2 Kompella的报文交互过程
与Martini方式相同,只不过VC表项的形式略有不同。见Martini的相关章节。
2.4.3 VC标签的计算
Kompella的实现相对复杂,主要是VC标签的计算部分,是最让人搞不明白的地方,因此有必要单独用一个小节来描述一下VC标签是如何计算出来的。
前面我们提到BGP交互的内容是标签块,也就是Label Block,标签块是一个连续的标签范围。那么为了清楚的描述这个标签块,需要定义几个值。首先定义标签块的起始标签LB(Label Base),然后定义这个块的大小LR(Label Range)。这样这个标签块就被清楚的定义了。
当PE上增加一个CE的相关配置时,需要指定标签块的大小LR,LB是PE自动分配的。这个标签块作为一个NLRI条目通过BGP传递到其它PE。当该CE配置被删除或者PE与该CE的连接失效,这个标签块也要被删除,BGP同样会做撤消通告。
假设,在开始部署的时候,CEm需要与远端其它CE建立两条VC,那么定义标签块的大小不能小于2。当然,为了今后扩容的考虑,我们可以定义Rang=10。无论Rang为多大,随着网络的扩容VC数量的增加,总会出现标签不够用的时候。这时候我们就需要重新定义Rang的大小,给一个更大的标签空间。但问题出现了,前面我们谈到标签块的数据是通过BGP的NLRI来传递的,并且这个标签块已经被用于计算VC标签和实际数据的转发。为了不破坏原有的VC连接,采用一个办法,就是给这个CE分配一个新的标签块,并且作为一条新的NLRI通过BGP通告。也就是说一个CE的标签空间可能是由许多个标签块组成的(Rang等于LR的总和),这种机制解决了网络扩展的需求。多个标签之间的联系通过一个偏移量来定义LO(Label-block Offset)。LO标志出了前面所有标签块大小的总和。比如第一个标签块的LR为100,LO为0;第二个标签块的LR为50,那么LO为100;如果有第三个标签块,它的LO就是150。LO会在VC标签计算被使用。现在每一个标签块都可以用三个参数来描述,那就是LB/LR/LO。
CE ID是在同一个VPN内唯一标识CE的参数。在同一个VPN内,每个CE,其CE ID必须是不同的,CE ID会在每一个NLRI中携带,这样就可以将标签块和对应的CE关联起来。在Kompella中,CE ID也被用于VC标签的计算。
假设PEk本地有一个CE-k,其CE ID为k,收到远端PE-m发过来的CE-m的一个或多个标签块,根据Kompella规定,CE-k连接到CE-m的标签必须满足以下两个条件:
(1)LOm <= k < LOm + LRm
然后从标签块LBm/LRm/LOm中选择标签,标签值为:
(2)LBm+k-LOm
公式(1)的右半部分很好理解,结合公式(2),如果不能满足k < LOm + LRm,CE-k选用的标签将超出LBm/LRm/LOm标签块的范围。但为什么要求LOm <= k,其中包含着什么意义?事实上,理解了LOm <= k,也就理解了Kompella标签分配算法中隐含的思想。
根据前面的叙述,LOm代表的是当前这个标签块之前CE-m的标签总和,也就是已经为CE-m分配掉的标签总数。要求 LOm<=k,就是规定,标签与CE ID是一一对应的。所有标签块里的第一个标签是分为CE 1的;所有标签里的第二个标签,是分给CE 2的。如果CE ID大于LOm,那么说明这个CE已经无标签可分了。CE ID如果是不连续的,那么LOm里面的标签有些会空余出来,这些已分配标签留给谁用呢?当然是留给CE ID比LOm小的CE使用。这反映了Kompella标准设计者的一个默认假设,即,如果一个CE ID为k,那么从0到k的CE ID都应该会被应用,并因此为这些CE预留了标签。
这就提出了一个问题,如果在配置CE ID时,不按自然数顺序编号,而是跳跃性的配置,一些CE ID配置得特别大,就会导致跳跃区域的CE ID没有被使用,但系统仍然给其预留标签,从而浪费标签,这是标准所不乐见的。因此,用户在配置时,最好能对CE顺序分配CE ID,这样能作到最节省的使用标签。
要求LOm <= k,事实上反映了Kompella标准设计者的一个美好愿望:用户配置时,能顺序配置CE ID,这样标准中的标签分配算法就能作到最节省标签空间。
下面详细描述了计算VC标签的过程。假设PE-k本地有一个CE-k,CE ID为k,收到远端PEm为CE-m分配的一个标签块LBm/LRm/LOm。
首先检查从PEk收到CEm的封装类型是否与CEk的相同,如果不一致,停止处理;
检查是否 k=m,如果是,报错“CE ID k has been allocated to two CEs in VPN X (check CEm at PEk)”,然后停止处理;
如果CEm有多个标签块,检查这些标签块是否有满足LOm <= k < LOm + LRm,如果任何一个标签块都不满足,报错 “Cannot communicate with CE m (PE A) of VPN X:outside range”然后停止处理;
检查和CE k相关的所有的标签块是否有满足LOk <= m < LOk + LRk,如果任何一个标签块都不满足,报错 “Cannot communicate with CE m (PE A) of VPN X:outside range”然后停止处理;
检查PEk和PEm之间的外层通道是否正常建立,如果没有就停止处理,这里假设为LSP隧道,标签为Z;对于外层隧道的判断决定了是否为一个VC计算VC标签,这一点与L3VPN不同。如果外层隧道没有建立,就不应该为VC计算标签。
PEk为CE-m分配内层出标签为(LBm + k - LOm) ,PEk为CE-k分配内层入标签为(LBk + m - LOk);
PEB到PEA的外层隧道的标签为Z;
内外层标签都已经计算出来,VC处于UP状态,可以用于二层报文的传输了。
我们分阶段来看一个例子:前提是PE之间都是通过BGP来交换标签块的信息。全部公网LSP隧道是正常UP的状态,我们只关心VC标签的计算。图中CE1的CE ID为1,以此类推。在下面的例子中CE22是一个单独的VPN,并且没有建立任何连接,但是PE1同样会为CE22欲留一个标签块。
图8 Kompella的VC标签计算例子
假设标签块的分配如图所示。PE1首先为CE1分配标签块1000/5/0,并且收到CE3的标签块1010/2/0。根据前面的计算规则可以计算出VC的入标签及出标签(绿色部分)。同时PE1上还连接了另一个CE22,PE1为它分配的标签块为1005/50/0(接着CE1的标签块继续分配),CE22可能目前并没有建立连接,是为今后的扩容做准备,因此不会为CE22计算标签。CE1与CE3之间隧道的标签计算过程如下,CE1为k侧,CE3为m侧:
PE1侧的判断:LOm <= k < LOm + LRm 0 < 1 < 0+2 满足条件
LOk <= m < LOk + LRk 0 < 3 < 0+5 满足条件
PE1进行VC标签计算:出标签为 LBm + k – Lom 1010 + 1 – 0 = 1011
入标签为 LBk + m – Lok 1000 + 3 – 0 = 1003
PE2侧的判断:同PE1,肯定是满足条件的。
PE2进行VC标签计算:出标签为 LBm + k – Lom 1000 + 3 – 0 = 1003
入标签为 LBk + m – Lok 1010 + 1 – 0 = 1011
图9 Kompella的VC标签计算例子(续)
一个新的CE13加入了绿色的VPN(黑体字部分),需要与CE1建立一条VC。目前为CE1分配的标签块大小为5,而CE ID 13大于CE1的Rang(5),所以需要更改PE1上CE1的Rang配置,这个例子中修改为15。这样PE1会为CE1分配第二个大小为10的标签块:1055/10/5(接着CE22的标签块继续分配)。PE2会收到CE1的两个标签块1000/5/0和1055/10/5,根据计算公式: 5 < 13 < 10 + 5命中CE1的第二个标签块,再判断对端CE ID与本端标签的关系0 < 1 < 4 + 0 。两个条件都满足,因此根据公式进行VC标签计算(图中黑体字部分)。
根据上面的例子,我们可以看出,如果CE ID不连续,那么Kompella方式的标签分配是会造成浪费的,所以在部署的时候最好配置连续的CE ID。从另一个角度看,考虑到VLL技术的特点,在一个PE上建立的VC数量是非常有限的。因此,即使有些浪费,也完全可以忽略不计。在实际的厂商实现中对一个CE的Rang可配置大小可能会有一些限制,比如500或者1000。这个数目对于一个CE而言已经足够大了。
在网络的实际部署中,有可能出现这样的情况,网络管理员习惯上用CE ID来标志这个CE的位置,因此CE ID有时候会配置的很大,这样就会造成大量的标签空间浪费,甚至有可能超出厂商的实现中对于Rang的限制。解决的办法是可以用CE的名字(字符串)来描述CE的位置,并且建立一个表格记录每个CE对应的CE ID。
2.4.4 VC标签的交互信令
为了交互VC信息,Kompella对MPBGP的NLRI部分做了扩展。用于携带L2VPN的信息。与L3VPN类似,Kompella方式的L2VPN也使用了RD和RT的信息。需要重点提及的一点是VLL技术必然是点到点的VC,如果一个CE需要与多个CE建立VC,那么就需要有多个接口或者子接口。虽然在同一个VPN内,两个CE之间必须有VC连接才能够直接通讯。
下面是NLRI中描述标签块的信息,在可变长的TLV部分有一个CSV(Circuit Status Vector)部分用于描述标签块的LR。
图10 对MPBGP的扩展
为了携带更多的L2VPN信息,定义了一个新的扩展属性
图11 layer2-info extended community
H3C设备上一个携带L2VPN信息的UPDATE报文是这样的。
图12 携带L2VPN信息的UPDATE报文
有一个部分没有被解码出来,就是CSV,在这个例子中可以看到跟在LB后面还有几个字节的数据,其中LR是0x14,也就是20。
2.5 VLL的跨域问题
VLL的跨域问题与实现方式有关。CCC模式是单层标签,因此只要ASBR之间建立静态LSP,那么就可以完成跨域。我们对照L3VPN中的三种跨域方法来分析一下L2VPN中的其它三种方式。
Option A是部分可以实现的,ASBR互相作为CE-PE在L2VPN的应用中存在一个问题,就是ASBR之间到底使用了什么样的链路连接,是否与VC的封装是一致的。如果恰好VC数量不多,而且ASBR之间也采用了同样封装的链路,那么SVC、Martini、Kompella三种方式的跨域都是可行的,不过因为每一条VC都需要对应ASBR之间的一个子接口,与L3VPN比较,需要消耗更多的资源和更大的配置量。这种模式只能在VLL部署的初期作为一个临时方案,不推荐使用。
Option B需要在ASBR处对内层和外层标签都做交换,目前看来并不适合L2VPN。
Option C显然是最好的解决方案,SP网络设备只需要在不同AS的PE上建立外层隧道就可以了。L2VPN的信息只是在PE间交换,对资源的消耗小,对配置量也没有什么增加。