1 MPLS基础
1.1 MPLS基本概念
- MPLS(Multiprotocol Label Switching),多协议标签交换,一种新型的由多种协议组成的转发机制,数据在MPLS网络中是根据标签信息进行转发
- MPLS基于报文头部的标签以及FLIB(转发标签信息表)进行数据转发
- 由于标签是定长,而路由表是最长匹配原则,所以自然查找效率更高,转发速度更快;
- 然而,现在网络设备都是基于ASCI芯片,转发都是线速转发,所以MPLS速度优势没有了,那么为什么仍在使用呢?因为存在基于MPLS的增值业务
■ MPLS VPN(运营商专线)
可以稳定、安全的为企业提供内网互通服务
■ MPLS 流量工程(MPLS TE)
可以根据链路的拥塞情况动态选路
- MPLS能够支持或者说承载多种三层协议(如IPv4、IPv6)
- MPLS 本质是一种2.5层的协议(介于网络层和数据链路层之间),可以支持多标签(标签栈)的封装;
1.2 MPLS相关表
1.2.0 三个层面
- 控制层面
- 概念:控制层面为数据层面转发数据提供了各种必要的信息,是各种协议工作的层面。
- 作用:为数据层面提供计算出的相应的素材,同时管理设备也是使用控制层面(管理层面的话高端设备会加)
- 主要占用资源:CPU
- 相关表项:RIB(路由表)、LIB(标签表)、OSPF邻居表、OSPF的LSDB、BGP的数据库…
- 转发层面
- 概念:网络设备中,对数据的各种具体的处理、转发过程都属于数据层面的范畴。
- 作用:控制层面构建了路由表等数据发送的必要信息,数据层面根据这些信息来发送数据。
- 主要占用资源:专用硬件资源(ASIC芯片)
- 相关表项:FIB(CEF转发表)、LFIB(标签转发表)、Adjacency Table、switching Cache、MAC…
- 数据层面
- 概念:数据层面是转发层面的父级
- 作用:除了负责转发层的将数据转发到一个接口,还负责数据的其他处理操作(上下标签,添加IP头部等等)
- 主要占用资源:专用硬件资源(ASIC芯片)
- 相关表项:涉及真实数据的处理操作都可以算是数据平面的操作
1.2.1 涉及的表
- 控制层
- 路由表(RIB)
查看命令:show ip route
- 标签表(LIB)
查看命令:show mpls ldp bindings
转发层是控制层的智慧结晶,设备最终报文转发依赖于转发层表项
- 转发层
- 转发表(FIB/CEF)
查看命令:show ip cef detail
- 转发标签表(FLIB)
查看命令:show mpls forwarding-table
注意:
标签转发表设计初始版本存在本地直连路由前缀的条目;
而由于PHP机制的出现,标签转发表不再包含本地直连路由前缀的条目;
PHP机制出现前(存在本地直连路由前缀条目)
PHP机制出现后(不存在本地直连路由前缀条目)
1.2.2 表的关联
- 在启动LDP之前,FIB表由RIB表生成
- 在启动LDP之后,新FIB表由旧FIB表和LIB表共同生成,来帮助LSR边界设备处理MPLS标签的转换动作(pop或者push)
- FLIB表由FIB和LIB组成,其中FLIB选择出站标签以及出接口根据的是FIB表中路由前缀对应的出接口
1.3 MPLS的名词
- LDP
Label Distribution Protocol标签分发协议,用于为自身路由前缀分发相应的标签,以及分享自身标签信息给LDP邻居和学习来自邻居的标签信息; - LSR
Label Switch Router标签交换路由器;是一种支持MPLS的路由器,能够理解MPLS标签并且能够在数据链路层面对MPLS标签包进行交换; - LSP
Label Switch Pah标签转发路径,LSP是报文在穿越MPLS网络或者部分MPLS网络时的单向路径; - FEC
Forward Equal Class,转发等价类;也就是MPLS标签转发这种方式可以等价于任何一种转发方式;自然标签转发的类(也就是标签)就等价于任何一种其他转发方式的类,在传统网络中,标签就等价于路由前缀;也就是说FEC就是路由表项(前缀+掩码);
1.4 MPLS的过程
在所有表项都建立完成的基础上,我们使用R1去ping 30.0./24网段,则有以下步骤
R1的操作流程:
- 产生ICMP载荷,封装源目IP
查找CEF表
中匹配目的IP的最长路由前缀,且压上200的tag将载荷转发至相应出接口- 根据出接口封装二层
- 转发
R2的操作流程:
- 接收报文
- 解封装数据链路层,并根据索引将载荷交给LDP进程处理
查询LFIB表
,根据接收报文匹配的进站标签200替换为出站标签300,然后转发对应接口R3的操作流程:
- 接收报文
- 解封装到数据链路层,并根据索引将载荷交给LDP进程处理
查询LFIB表
,将接收报文匹配的进站标签300弹出(也就是剥离这个2.5层)查询FIB表
中匹配目的IP的最长路由前缀,发现是直连路由直接解封装到载荷
1.5 MPLS的标签
- MPLS标签结构
- Label 标签号
- EXP 实验位,用于QoS流量工程
- BoS 默认置0,表示只有单标签;如果在此标签基础上还有封装标签,则此位置置1;
也可以看出MPLS是2.5层的封装,所以也会根据FLIB表的下一跳IP来前期对应的MAC进行二层封装- TTL 类似IP包的TTL,用于防止标签环路
- MPLS标签动作
- Push:将不带标签的数据加上标签进行转发
- Swap:正常标签或者0号标签进行local label到outgoing label标签的交换
- Pop标签:弹出首层标签,对于本地LIB存在imp-null也执行该动作
- Untagged标签:弹出所有标签,应对暂时的LIB和FIB不同步问题
当检测到进站标签是0,则直接弹出,进入FIB表的比对环节;
- MPLS特殊标签
- 标签0 显式空
- 标签3 隐式空
- 标签1 路由器报警标签
- 标签14 OAM报警标签
- 0-15都为被保留标签,还有一些功能暂时没有定义,正常标签从16开始使用
1.6 MPLS小结
- 采用MPLS,可避免IP路由逐条转发情况,减少数据报的深入分析,借助标签建立二层的快速转发路径,使得数据沿着一条预先建立的路径快速转发
- 数据包在MPLS网络的入口便捷路由器被进行一次三层查找,而在此后的LSR只是进行简单的标签交换动作,无需进一步分析三层信息
- 每一个LSR必须在数据转发之前建立好LIB、LFIB;当LSR收到标签数据帧时,将数据帧中的标签在LFIB表中进行查找,在根据LFIB表中指示的相关动作对标签进行压入、弹出、交换、移除等动作
2 LDP
2.1 LDP的工作原理
- HELLO包
- 作用:用于邻居的发现和后期保活,以及发现传输IP为后续TCP建立连接提供基础
内容:
- 源IP是出接口IP,目的IP是所有路由器都能接收的224.0.0.2组播
- 源端口和目的端口都是UDP 646
- LDP ID共6字节由LSR ID和Label Space ID组成
- Label Space置0表示基于平台分发标签(默认),而基于接口分发标签则本地同一前缀分发给不同邻居的Space ID会不一样,这比较占用资源但是更安全
- 传输地址除非手动指定,一般情况下等于LSR ID
- LSR ID的选举过程同OSPF 的RID选举过程
- initialization / KeepaliveM Msg
- 作用:进行参数的协商,如果通过则回复Keepalive Mag来确认参数协商通过
内容:
- 目的IP为对方的LSR IP
- 目的端口号为 TCP 646,但是源端口号随机
- 协商传输包括版本号和保活计时器
- Label Mapping Msg
- 作用:传递给邻居相应前缀对应的标签
- 内容:前缀和标签的组合
2.2 LDP协议下MPLS收敛
注意:下图中的RIB表表示的就是初始状态下的FIB表,也就是还没加入LIB重建的FIB表
- 链路出现故障后
- IGP如OSPF等待邻居计时器超时,然后
IGP开始收敛,RIB重建
- 此时LDP邻居还没来得及收敛LIB还没变化,不过并不影响结果
LFIB表根据变动的RIB表和没变化的LIB表进行重建
,选择新的下一跳以及标签
- 链路重新恢复
- 则IGP重新开始计算收敛,恢复正常下一跳,
FIB表重建
下一跳- 此时B和C的LDP邻居还没起来标签还没交换,
LIB还未更新
- 由于FIB下一跳改变,而LIB还未更新无对应信息,所以
FLIB重建时出站为Untagged
,弹出所有标签,来解决短暂的FIB和LIB表不同步的问题
(因为既然FIB表内有条目存在,则一定可以转发普通未带标签的报文)
其实表项之间的联系可以用数据库的方式来理解
- 将RIB以及LIB中Network和NH进行比对,相同则合为一项,共同构成LFIB和FIB
- 不相同则先把LFIB的出站标签打上Untagged,这种设计可以解决暂时性的FIB和LFIB表项不同步的情况,但是也可能会导致路由黑洞等问题的存在或者其他问题,可以使用MPLS TE或者LDP会话保护来解决问题,具体后面再谈;
2.3 LDP的PHP机制
-
概念
PHP(Penultimate Hop Popping),次末跳弹出机制。在传递给LDP邻居本地路由前缀的标签时,区别于其他路由前缀的正常标签,而使用意为implict-null(标签号为3)的标签。邻居在收到该标签之后,则默认对于这类出站Tag转发动作为“弹出标签”而不是替换携带该标签。该机制的设计初衷是为了加快目的设备处理报文的速度(将查询FLIB+FIB表 压缩为 仅查询FIB表) -
过程
-
Imp-null 概念
Implict-null,隐含空,邻居在收到该标签之后,对于出站TAG为imp-null的报文执行“标签弹出”动作然后作为普通报文传递,而不是替换为“imp-null(3)”的标签传递;
- Imp-null 优势和缺陷
- 优势
1 加快了报文的整体处理效率,总体上可以节省掉目的设备遍历LFIB表的时间;
2 更加节省资源以及加快遍历的速度,由于“imp-null”的设计理念,所以设备就不需要利用LFIB表处理带TAG的自身路由前缀信息了(因为传递给自身的前缀路由信息Tag已近被弹出,一定不带TAG),所以此时自身LFIB表中就不用存在自身前缀路由的信息;- 缺陷
1 不利于流量工程,标签的提前弹出意味着有一段的报文是不携带标签的,而标签的组成里不止包含标签号字段,也包含了用于QoS的EXP字段,这可能会影响流量的整体统计- 缺陷的解决办法——“exp-null”
使用“exp-null”即“explict-null”“显示空”,将直连路由器前缀对应的Tag统一用Tag 0(意为“显示空”即“exp-null”)的形式传递给LDP邻居,邻居在转发出站Tag为exp-null的报文时,会携带这个标签即Tag 0,这样就可以避免出现一段距离不存在标签而导致流量工程统计不完整的情况发生;- 思考——为什么不直接让直连路由前缀直参与Tag的随机分配,而是使用“显示空”来解决?
“显示空”显然是一种夹在“隐含空”和“全部随机分配”模式之间的一种过渡模式;如果本地直连路由也随机分配,则意味着本地需要LFIB存在相应的直连路由前缀的条目来处理这些携带正常Tag,这显然增加了设备的负担同时遍历表项也减缓了设备处理报文的速度;而“显示空”则不需要LFIB存在本地直连路由前缀的表项(也没有进站Tag为0的表项),只需要在收到带Tag=0的报文时,直接执行弹出操作,不需要进行LFIB的遍历,一方面节省了资源一方面也加快了报文处理速度;
2.4 LDP的Loop Detection
- 概念
Loop Detection,环路检测,通过一些方法来进行LDP的防环,具体方法如下
- 方法
- 依赖IGP进行防环
因为FLIB根据FIB表的下一跳IP选择出站Tag,且IGP自身有防环功能,所以FLIB也自带一定的防环功能;- TTL Propatation
TTL复制,通过在MPLS标签内置TTL字段来进行防环,这个TTL复制自IP层内的TTL,具体的TTL Propatation过程下面会细说;
- TTL Propatation
- 优势
o 保证了TTL的连续性
o 具有一定防环功能(和不开启TTL复制相比)- 缺陷
o 由于保证了TTL的连续性,外部可以通过Traceroute来查看中间节点的所有IP,不安全- 缺陷解决
o 关闭TTL Propatation功能
R1(config)#no mpls ip propagate-ttl forwarded/local
forward针对穿越该路由器流量,local针对本地产生流量
o 则MPLS标签内TTL使用255开始随传递缩减而不使用IP内的TTL
o 这种方法虽然保证了节点的安全性,但是不能保证TTL的连续性,且防环功能较差(得循环255次才丢包)
2.5 LDP基本命令
配置类
- 设置LDP 的 RID
R1(config)#mpls ldp router-id interface[force]
- 开启接口的LDP,激活接口的标签交换能力
R1(config-if)#mpls ip
- 标签范围设置
R1(config)#mpls label range A B
- 在全局模式下选择标签协议(默认LDP)
R1(config)#mpls label protocol ldp | tdp
- 在接口选择标签协议(both表示根据对端选择其中一种,而者不能同时运行)
R1(config-if)#mpls label protocol ldp | tdp | both
- 取消TTL的复制行为
R1(config)#no mpls ip propagate-ttl
显式空这是
R1(config)#mpls ldp explicit-null
查看类- 查看MPLS LDP的计时器和其他参数
show mpld ldp parameters
- 查看LDP的邻居建立情况
show mpls ld neighbor
- 查看是否收到邻居的LDP发现报文
show mpld ldp discovery
- 查看LDP 标签绑定表(FIB)
show mpld ldp binding
- 查看标签转发表(FLIB)
show mpls forwading-table
- 查看快速转发表(CEF)
show ip cef
- 条件通告——选择特定邻居通告特定前缀
R1(config)#mpLs LDP advertise-labels [for prefix-access-list][to peer->access-list]
注意在此之前需要先输以下命令,不然默认通告全部的LDP邻居
R1(config)#no mpls ldp advertise-labels
3 路由汇总对MPLS的影响
- 路由汇总也算是一种本地产生的路有前缀,所以触发了PHP机制,导致链路中出现没带MPLS标签的报文,这种行为将LSP分为了两段
- 在某些环境,如MPLS VPN、TE要慎用,因为中间设备是查询FIB表,而表内可能没有目的IP的条目,也就可能导致丢包情况的发生
- 情况介绍
AS1234内起OSPF邻居,不宣告R1R5以及R4R6网段进OSPF;
同时R1R2处于一个OSPF AS,R2R3R4处于一个OSPF AS,R2属于OSPF的ABR,汇总1.1.1.1/32为的网段为1.1.1.0/24传递给隔壁AS;
EBGP邻居间直连建立邻居,AS1234内就R1和R4用环回接口建立IBGP邻居,并且next-hop-self;
分析
6.6.6.6 ping 5.5.5.5
- 报文到达R4
- R4查看FIB表,将封装R3传来的对应1.1.1.1网段的标签 (Next-hop-self后BGP表中5.5.5.5前缀对应的下一跳的IP就是1.1.1.1网段的IP)然后转发给R3
- R3发现是标签包查看FLIB表,弹出标签转发给R2(因为汇总缘故1.1.1.0/24是R2的直连路由,所以传递给R3的imp-null)
- R2收到一个正常的IP包,查看FIB表发现没有对应的条目,直接丢包
思考:显式空可以解决路由汇总带来的问题吗?
答案:不行,因为“显式空”只是让R3传递给R2的过程中携带了标签,但是R2收到TAG=0的标签也会直接弹出TAG,最后还是得查询FIB表,所以没有意义;
4 MPLS的负载均衡
实际上MPLS的负载均衡是依靠网络层的负载均衡来实现的
- 网络层负载均衡的类型
- per-packet
根据包来做负载均衡,处于负载均衡的几个接口轮流转发包- per-destination(默认负载均衡模式)
根据对包内“源目地址对”做哈希算法,来确定该包是从哪个接口发出,只要源目地址对不变则一直从一个接口发出
- 修改方式:
R1(config-if)#ip load-sharing ?
per-destination Deterministic distribution
per-packet Random distribution
- MPLS的负载均衡
- per-packet
根据包来做负载均衡,处于负载均衡的几个接口轮流转发包- per-destination
解封转MPLS标签后,根据底层IP的前面两个字节的version字段来判断是IPV6还是IPV4,
然后根据匹配的哈希算法计算要转发到哪个接口,然后再封装MPLS和二层从对应接口发出;还有一种极端情况,如果是多标签,则底层还是标签,这种情况根据底层的标签决定;
5 BGP路由黑洞新解决方案——MPLS
需要注意:
- LDP不会给路由表中的BGP条目分配标签;
- FIB表中对于BGP前缀impose的标签应该是这个前缀在BGP表中对应的下一跳的IP地址
5.1 方案一
- 拓扑
- 分析
6.6.6.6 ping 5.5.5.5 可以Ping通 - WHy
此时由于没有配置IBGP之间的Next-Hop-Self,且eBGP是直连建邻,所以在R4上的BGP路由中 去往5.5.5.5的下一跳就是10.1.15.0 - 过程分析
- 报文到达R4
- R4查看FIB表,将封装R3传来的对应10.1.15.0网段的标签 (因为没有Next-hop-self的情况下R6的BGP表内的5.5.5.5前缀的下一跳应该是R5的出接口IP也就是10.1.15.0的网段的IP)然后转发给R3
- R3查看到标签包通过FLIB表加上新的标签转发到R2
- R2发现是标签包查看FLIB表,弹出标签转发给R1(R1对于直连路由分配imp-null给R2)
- R1收到之后查看FIB表转发给R5
- 回程省略…
- 过程如下
5.2 方案二
在方案一的基础上的改动:
- OSPF不再宣告R1R5和R4R6这两个网段的路有前缀
- R1和R4建立IBGP邻居的同时Next-hop-self
- R1和R4使用直连建邻
- 拓扑
- 分析
6.6.6.6 ping 5.5.5.5 失败 - WHy
此时由于配置IBGP之间的Next-Hop-Self,R1和R4是直连建邻,所以在R4上的BGP路由中 去往5.5.5.5的下一跳就是10.1.12.0 - 过程
- 报文到达R4
- R4查看FIB表,将封装R3传来的对应10.1.12.0网段的标签 (Next-hop-self后BGP表中5.5.5.5前缀对应的下一跳的IP就是10.1.12.0网段的IP)然后转发给R3
- R3发现是标签包查看FLIB表,弹出标签转发给R2(10.1.12.0是R2的直连路由,所以传递给R3的imp-null)
- R2收到一个没标签的普通包,查询FIB表,发现没有5.5.5.5网段条目,直接丢弃
- 过程
5.3 方案三
在方案二的基础上
- R1和R4之间用loopback接口建立邻居关系
- 这样Next-hop-self的的IP就是环回接口的IP地址
这样PHP只会发生在R1和R2以及R3和R4之间,不会发生在R3到R2之间,这样就不会出现标签中途失去导致路由不可达的问题,也是最完美的解决方案了;