MPLS TE SPF Example 1

SPF如何工作
    在链路状态路由协议中,每一个路由器都知道网络中的所有路由器以及连接到这些路由器的链路。在OSPF中,这些信息包含在链路状态通告(LSA)中;在ISIS中,这些信息在链路状态分组(LSP)中。
    一旦路由器知道其他所有的路由器及其链路,它就会运行Dijkstra最短路由优先算法来确定本路由器到网络中其他路由器的最短路径。

这个例子介绍了路由器A如何运行SPF建立自己的路由表的过程。
   在网络中的每一个路由器完成自己信息的泛洪后,所有的路由器都知道了其他的路由器和它们之间的链路。所以每一个路由器上的链路状态数据库(LSDB)都像表所示:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
路由器                    {邻居,代价}对
A                         {B,5}{C,10}
B                         {A,5}{C,3}{D,8}
C                         {A,10}{B,3}{D,4}
D                         {B,8}{C,4}
=========================================================
接下来路由器A如何处理这些信息?
在SPF计算中,每个路由器维护了两个列表:
·一个在通往目的地的最短路径上的结点列表。这个列表也称为路径列表(PATH list)或者路径组列表(PATHS list)。对于路径列表很重要的一点就是列表记录了到目的地址的最短路径。
·可能在也可能不在到目的地址的最短路径上的下一跳列表。这个列表称为TENTatitve或者TENT列表。
每一个列表都是从当前路由器角度出发的{路由器,距离,下一跳}({router,distance,next-hop})三元组组成的表。
    为什么是三元组?你需要知道在PATH列表和TENT列表中要到达的路由器,所以三元组的第一部分毫无疑问是路由器的名字。实际中,往往是路由器的RID而不是文本名, 使用路由器的名字。下一跳是要到达结点就必须先经过的路由器。三元组的第三部分是距离,表示到达结点的代价。

    为什么所有表中的名字都用大字?这只是一种写法,它们并不是大写的首字母,仅仅是采用了大写。SPF计算的大部分例子,以及很多和SPF有关的调试内容都和PATH和TENT列表中的内容有关。

    计算每一个结点的最短路径算法很简单。每个路由器运行以下算法:
    第一步,把自己列入PATH列表,并且距离为0,下一跳也是自己。路由器在运行SPF时,把自己当作"self"或者根结点,因为这个结点是最短路径树(shortest-path tree)的根结点。
    第二步,从PATH列表取出刚入的结点,这个结点称为路径结点(PATH node)。查找路径结点的邻居列表,把列表中的每一个邻居加入TENT列表,下一跳都设置为PATH结点,除非该邻居已经在TENT或者PATH列表中并且代价较小。把加入TENT列表的结点称为TENT结点。把到达TENT结点的代价设为从根结点到PATH结点的代价加上从PATH结点到TENT结点的代价之和。如果加入的结点在TENT列表中已经存在,但是代价较大,就用当前的结点取代代价较高的结点。
    第三步,在TENT列表中找到代价最低的邻居,把邻居加入到PATH列表中,重复第二步。如果TENT列表为空,就停止。

For example:
如上图中路由器A通过此方法建立路由表的过程。

第一步,把自己加入PATH列表,距离为0,下一跳是自己。路由器A的数据库如表
路由器A的PATH列表和TENT列表
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PATH列表                          TENT列表
{A,0,0}                           (empty)
==========================================================

第二步,从PATH列表取出刚入的结点,这个结点称为路径结点(PATH node)。查找路径结点的邻居列表,把列表中的每一个邻居加入TENT列表,下一跳都设置为PATH结点,除非该邻居已经在TENT或者PATH列表中并且代价较小。如果加入的结点在TENT列表中已经存在,但是代价较大,就用当前的结点取代代价较高的结点。

在本例中,{B,5,B}和{C,10,C}加入了TENT列表,如表:
第二步之后的PATH列表和TENT列表
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
PATH列表                         TENT列表
{A,0,0}                          {B,5,B}
                                 {C,10,C}
=====================================================

第三步,在TENT列表中找到代价最低的邻居,把邻居加入到PATH列表中,重复第二步。如果TENT列表为空,就停止。

{B,5,B}移到了PATH列表中,因为这是到B的最短路径。因为{C,10,C}是路由器A仅有的另一个邻居,而到C的代价大于到B的代价,不可能存在和现在已知相比到B的更小代价的路径。

第三步之后的PATH列表和TENT列表
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PATH列表                          TENT列表
{A,0,0}                           {C,10,C}
{B,5,B}
======================================================

第四步,重复第二步。从PATH列表取出刚入的结点,这个结点称为路径结点(PATH node)。查找路径结点的邻居列表,把列表中的每一个邻居加入TENT列表,下一跳都设置为PATH结点,除非该邻居已经在TENT或者PATH列表中并且代价较小。如果加入的结点在TENT列表中已经存在,但是代价较大,就用当前的结点取代代价较高的结点。

检查路由器B的邻居。路由器B到C的链路代价是3,到D的链路代价是8。路由器C加入了TENT列表,代价(从A经B到C)等于8,它是5(从"self"到B的代价)加上3(从B到C的代价)得到的,下一跳是B,然后路由器D也加入了TENT表,代价是13,等于5(从根结点到B的代价)加上8(从B到D的代价),下一跳是B。因为经过B到C的代价低于经过C到C的路径代价10,所以代价为10的路径从TENT列表中删除。

第四步之后的路由器A上的PATH列表和TENT列表

第五步,在TENT列表中找到代价最低的路径,加入到PATH列表中,然后重复第二步。如果TENT列表为空,就停止。从{C,8,B}到C的路径移到了PATH列表中。

第五步之后路由器A上的PATH列表和TENT列表
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PATH列表                          TENT列表
{A,0,0}                           {D,13,B}
{B,5,B}                           
{C,8,B}
============================================================

第六步,从PATH列表取出刚放入的结点,查找路径结点的邻居列表,把列表中的每一个邻居加入TENT列表,除非该邻居已经在TENT或者PATH列表中并且代价较小。如果加入的结点在TENT列表中已经存在,但是代价较大,就用当前的结点取代代价较高的结点。

在此规则下,代价为12的经过B到D的路径(实际是B->C->D)取代了代价为13的经过B->D到D的路径。

第六步之后路由器A上的PATH列表和TENT列表
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
PATH列表                          TENT列表
{A,0,0}                          {D,13,B}
{B,5,B}                          {D,12,B}
{C,8,B}
======================================================

第七步,在TENT列表中找到代价最低的邻居,加入到PATH列表中,然后重复第二步。如果TENT列表为空,就停止。
到D的路径移到了PATH列表。

第七步之后路由器A上的PATH列表和TENT列表:TENT列表为空
++++++++++++++++++++++++++++++++++++++++++++++++++++++
PATH列表                         TENT列表
{A,0,0}                          
{B,5,B}
{C,8,B}
{D,12,B}
=======================================================

第八步,在TENT列表中找到代价最低的邻居,加入到PATH列表中,然后重复第二步。如果TENT列表为空,就停止。
TENT列表为空,因为D没有不在PATH列表上的邻居,所以停止。这时,PATH列表就成了A的路由表。

路由器A的路由表
+++++++++++++++++++++++++++++++++++++++++++++++++++
节点              代价              下一跳
A                 0                 self(自己)
B                 5                 B(直连)
C                 8                 B
D                 12                B
====================================================

这就是SPF算法工作的过程。完成后,拓扑结构(根据路由器A的路由表)看起来如图。

可以看出,来自路由器A的流量从来不会经过从A到C的链路或者从B到D的链路。
有两件事出乎你的意料。第一,经过B到D链路的流量只来自于A。
第二,路由器A到路由器C之间的链路根本没有用,因为它的代价10太高了。在实际的网络中,这样的链路实际由于昂贵的权重而废止,除非网络中的其他链路失效才会使用。实际的SPF实现比这里描述的要复杂一些,但是这里介绍的是它的主要思想。

原文地址:https://www.cnblogs.com/cyrusxx/p/12824082.html