PIM SM 报文转发规则
来源:互联网 发布:软件著作权 电话 编辑:程序博客网 时间:2024/04/18 07:29
规则描述
定义
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)状态转发
伪代码
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 SM 报文转发规则
- PIM-DM/SM
- PIM-DM与SM对比
- PIM-DM/SM (1)
- RPF机制,PIM-DM工作机制,PIM-SM工作机制
- RPF机制,PIM-DM工作机制,PIM-SM工作机制
- PIM SM + IGMP Snooping 适用性测试
- IP Multicast: PIM-SM Auto-RP and BootStrap
- PIM-SM协议初探(一)路由角色选举
- PIM-SM协议初探(二)RPT构建
- PIM-SM协议初探(三)SPT构建
- PIM-SM协议内核触发机制及协议运行机制记录
- PIM SM + IGMP Snooping 适用性测试(二) ttl 问题
- PIM-DM/SM (2)(协议包的区别)
- 组播(IGMP,IGMP SNOOPING,PIM-DM,PIM-SM,MSDP,MBGP)
- 简述 RPF机制,PIM-DM工作机制,PIM-SM工作机制
- 组播讲义(IGMP,IGMP SNOOPING,PIM-DM,PIM-SM,MSDP,MBGP)
- 关于Modbus 报文 (转发)
- hive分桶管理
- 配置aop报错: Pointcut is not well-formed: expecting 'name pattern' at character position
- [笔记分享] [Camera] MTK Camera Performance
- 《聊聊架构》笔记记录
- HDU
- PIM SM 报文转发规则
- 笨办法学 Python · 续 练习 35:解释器
- linux acl 改变特定用户的文件权限
- Helper2416开发板学习①环境搭建
- China Operating System 电脑操作系统 2016全球互联网排名
- sbl.py
- bzoj 1858: [Scoi2010]序列操作
- POJ
- 自己实现telnet程序