PIM SM 报文转发规则

规则描述


定义

iif 组播数据包进入路由器的接口;

oiflist 将组播数据包发送出路由器的接口列表;

上游 RPT/SPT上朝向 RP/Source的一侧

下游 RPT/SPT上朝向 G组成员的一侧

转发流程

组播报文进入路由器

1) 检查报文,如果组播源在路由器直连的子网上,重置(或启动)Keepalive 计时器;

2) 检查是否可以置位STPbit。如果此时在RPT到SPT的待切换状态,此步可以判断¹SPT是否建立完成并切换到SPT;如果此时已经在SPT状态,此步会判断SPT的条件是否仍然满足;如果置位STPbit后续会基于(S,G)状态转发报文,否则基于(*,*,RP)/(*,G)状态转发

3) RPF检查。检查数据包到达的接口iif,是否是根据TIB 状态计算出的应该到达的接口;

4) 判断如果数据包应该根据(S,G)状态转发,那么使oiflist==(S,G)状态计算出的下游接口,检查oiflist是否为空,不为空的话,重置(S,G)状态的Keepalive 计时器;

5) 判断如果数据包应该根据(*,*,RP)或(*,G)状态转发,使oiflist==(*,*,RP)或(*,G)状态计算出的下游接口,并且检查是否需要切换到SPT;

6) 最后,将iff从oifist 中移除,如果此时oiflist不为空的话,将数据包从oiflist 中发送出去


注:(S,G) SPTbit主要用于判断是基于(*,*,RP)/(*,G)状态转发还是基于 (S,G)状态转发

伪代码

PIM 转发流程伪代码
 On receipt of data from S to G on interface iif:
    if( DirectlyConnected(S) == TRUE AND iif == RPF_interface(S) ) {
         set KeepaliveTimer(S,G) to Keepalive_Period
        /* Note: a register state transition or UpstreamJPState(S,G)
           transition may happen as a result of restarting
           KeepaliveTimer, and must be dealt with here. */
    }
	
   if( iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined AND
      inherited_olist(S,G) != NULL ) {
          set KeepaliveTimer(S,G) to Keepalive_Period
   }
    // 前两个if主要用来重置计时器
   Update_SPTbit(S,G,iif) //判断是否可以置位SPTbit
   oiflist = NULL        //oiflist 置零

   if( iif == RPF_interface(S) AND SPTbit(S,G) == TRUE ) {
      oiflist = inherited_olist(S,G)
      // 基于(S,G)state 下转发
   } else if( iif == RPF_interface(RP(G)) AND SPTbit(S,G) == FALSE) {
     oiflist = inherited_olist(S,G,rpt)
     CheckSwitchToSpt(S,G)
      //基于(*,*,RP)或(*,G)状态转发,并判断是否开始SPT切换
   } else {
      /* Note: RPF check failed
         A transition in an Assert FSM may cause an Assert(S,G)
         or Assert(*,G) message to be sent out interface iif.
        此时说明RPF 检查失败 */
      if ( SPTbit(S,G) == TRUE AND iif is in inherited_olist(S,G) ) {
         send Assert(S,G) on iif
      /* 当接口(S,G) Assert state 处于“No Info”或“I am Assert Winner”时,
         如果从 inherited_olist(S,G)收到(S,G)报文,会再次发起Assert 流程,
         发送Assert(S,G),重置定时器;
        (S,G)处于“I am Assert Loser”的接口不会出现在inherited_olist(S,G)中 */
      } else if ( SPTbit(S,G) == FALSE AND
                  iif is in inherited_olist(S,G,rpt) {
         send Assert(*,G) on iif  //同上
      }
   }

   oiflist = oiflist (-) iif  //将iif从oiflist 中移除,如果在的话
   forward packet on all interfaces in oiflist

函数定义

DirectlyConnected(S) 如果组播源S 是路由器直连的某个子网,或者组播数据发自路由器本身,DirectlyConnected(S) 返回true
inherited_olist(S,G)是在(S,G) 状态下转发组播包的出接口,同时将(*,*,RP)状态,(*,G)状态,asserts 等考虑在内。详见下文描述;
inherited_olist(S,G,rpt) 是在(*,*,RP)  (*,G) 状态下转发组播包的出接口,同时将(S,G,rpt) prune 状态,asserts等考虑在内。详见下文描述;


Update_SPTbit 函数

    Update_SPTbit(S,G,iif) {
       if ( iif == RPF_interface(S)  //从SPT的上游邻居收到组播报文
             AND JoinDesired(S,G) == TRUE
             AND ( DirectlyConnected(S) == TRUE
                   OR RPF_interface(S) != RPF_interface(RP(G)) //RPT与SPT的上游接口不同
                   OR inherited_olist(S,G,rpt) == NULL  //RPT上没有任何组成员
                   OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
                        ( RPF'(S,G) != NULL ) ) /*如果RPT与SPT重合,立即根据SPT转发,但不立即Prune RPT */
                   OR ( I_Am_Assert_Loser(S,G,iif) ) {
          Set SPTbit(S,G) to TRUE
       }
     }

当路由器发现收到的组播包是从SPT上发过来的,即可确定SPT已经建立完成,应基于(S,G)状态转发。注意:当收到组播报文时才会执行Update_SPTbit(S,G,iif)

RPF' 指RPT或SPT上的上游邻居,除非PIM Assert 已经推翻正常的邻居选择

neighbor RPF’(S,G) {
if ( I_Am_Assert_Loser(S, G, RPF_interface(S) )) {
return AssertWinner(S, G, RPF_interface(S) )
} else {
return NBR( RPF_interface(S), MRIB.next_hop( S ) )
}

 inherited_olist(S,G,rpt)& inherited_olist(S,G)

inherited_olist(S,G,rpt) =
           ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) )
       (+) ( pim_include(*,G) (-) pim_exclude(S,G))
       (-) ( lost_assert(*,G) (+) lost_assert(S,G,rpt) )
							
   inherited_olist(S,G) =
       inherited_olist(S,G,rpt) (+)
       joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G)

joins(S,G)指那些收到(S,G)join的接口集;

prunes(S,G,rpt)指那些收到(*,G)join和(S,G,rpt)prunes的接口集;

pim_include(*,G)pim_include(S,G)可以指出那些有希望收到组播流的本地成员的下游接口集。通常情况下只有DR会关心本地成员,但是当assert 发生时,assert winner 会接替转发流量的责任,将组播流或特定源组播流发送到那些有本地成员的接口;

lost_assert(S,G,rpt)指那些收到了(*,G)joins, 但是输掉(S,G)assert的接口集

 pim_include(*,G) =
      { all interfaces I such that:
        ( ( I_am_DR( I ) AND lost_assert(*,G,I) == FALSE )
          OR AssertWinner(*,G,I) == me )
        AND  local_receiver_include(*,G,I) }

   pim_include(S,G) =
       { all interfaces I such that:
         ( (I_am_DR( I ) AND lost_assert(S,G,I) == FALSE )
           OR AssertWinner(S,G,I) == me )
          AND  local_receiver_include(S,G,I) }

   pim_exclude(S,G) =
       { all interfaces I such that:
         ( (I_am_DR( I ) AND lost_assert(*,G,I) == FALSE )
           OR AssertWinner(*,G,I) == me )
          AND  local_receiver_exclude(S,G,I) }

 local_receiver_include(*,G,I),当IGMP/MLD或其他机制任务接口I下的本地成员希望收到发往G的所有组播流,local_receiver_include(*,G,I)返回true;

local_receiver_include(S,G,I),当IGMP/MLD或其他机制认为接口 I 下的本地成员希望收到从 S 到 G 的组播流时, local_receiver_include(S,G,I)返回true;

local_receiver_exclude(S,G,I),当local_receiver_include(*,G,I)返回true,但没有本地成员希望收到来自源S的组播流时,local_receiver_exclude(S,G,I)返回true;

CheckSwitchToSpt(S,G)

CheckSwitchToSpt(S,G)函数决定是否可以开始从RPT切换到SPT:

 void
     CheckSwitchToSpt(S,G) {
       if ( ( pim_include(*,G) (-) pim_exclude(S,G)
              (+) pim_include(S,G) != NULL )
            AND SwitchToSptDesired(S,G) ) {
              # Note: Restarting the KAT will result in the SPT switch
              set KeepaliveTimer(S,G) to Keepalive_Period
       }
     }

SwitchToSptDesired(S,G)可以有不同的实现。比方说,可以设置“永不切换”策略,此时SwitchToSptDesired(S,G)永远返回false ,或者设置收到第一个组播包即返回true,也可以设定一个流量阀值,当组播流量超过阀值时返回true.

PIM Assert

多台PIM路由器在一个共享的LAN中,有可能会出现多台上游路由器向该LAN中发送同一个组播流,这会使组成员收到重复的组播报文。PIM 协议并不能防止多台上游路由器收到同一个join消息,但是当一个共享LAN中出现了重复的组播报文时,PIM路由器会发现,并选举出一个转发者负责将组播流发送到该LAN。这个选举过程依赖PIM Assert 消息。PIM Assert 消息中包含组播路由状态和到RP/Source的路由Metric 等,通常优选基于(S,G)状态转发的路由器,若都基于(S,G)状态转发则优选到Source Metric值最优的路由器。下图展示了多台PIM路由器在一个共享LAN上的情况:


-----------------------------------------------------------------------------------
本文译自RFC4601,作者增加了部分注释和描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值