网络实验(OSPF,BGP与组播)
本文章包含200张图片… 请务必慎重打开该文章…
该博客主要为网络实验的全面复盘, 包括: OSPF, BGP, 组播, 网络管理与MPLS.
参考了大量张力军老师的《计算机网络实验教程》, 通过ensp进行各项实验与分析.
后记, 本博客OSPF和组播的介绍比较系统比较好, 但是BGP不知道当时在整理的时候处于什么精神状态, 导致BGP的内容整理比较答辩…
VLAN
VLAN的简单配置
VLAN端口的几个类别:
-
Access:接收和发送数据包均不带有VLAN标签, 只属于同一个VLAN
-
接收报文:判断是否有vlan信息, 若没有则打上端口的PVID, 并进行交换转发, 若有则直接丢弃(缺省)
-
发送报文:将报文的vlan信息剥离, 直接发送出去
-
-
Trunk
-
收到报文:判断是否有vlan信息, 若没有打上端口的PVID, 并进行交换转发, 若有判断该端口是否允许该vlan的数据进入, 若可以则转发, 否则丢弃
-
发送报文:比较端口的PVID和将要发送报文的vlan信息, 若两者相等则剥离vlan信息, 再发送, 若不相等则直接发送
-
-
Hybrid: 与Trunk的不同在于允许多个Vlan报文不带标签, 而Trunk只允许默认的VLAN报文不带标签
-
接收报文的处理方式与Trunk相同
-
发送报文:判断该vlan在本端口的属性, 如果是untag则剥离vlan信息, 再发送, 如果是tag则直接发送
-
交换机选用S5700, 以下的若干配置需要注意:
- 配置vlan时, access端口也需要通过
link-type
指定后才能加入到vlan中
通过ensp分析一下trunk端口的转发过程, 拓扑结构如下:
以S1的配置为例:
1[S1-vlan2]inter g0/0/1
2[S1-GigabitEthernet0/0/1]port link-type access
3[S1-GigabitEthernet0/0/1]inter g0/0/24
4[S1-GigabitEthernet0/0/24]port link-type access
5
6[S1-GigabitEthernet0/0/24]vlan 2
7[S1-vlan2]port G0/0/1
8
9[S1-vlan2]vlan 3
10[S1-vlan3]port G0/0/24
11
12[S1-vlan2]inter g0/0/13
13[S1-GigabitEthernet0/0/13]port link-type trunk
14[S1-GigabitEthernet0/0/13]port trunk allow-pass vlan 2 3
令PC1 ping PC3, 在G0/0/13之间抓包, 如下所示:
ARP: 由于处在同一网段, 因而PC1(MAC地址为62:10
)直接在网段内发起ARP请求, 询问拥有2.11
的IP地址的主机, PC3(MAC地址为31:27
)收到后将自己的MAC返回; 而对于不同网段的通信请求, 源主机会将报文默认发给网关, 因而只需要知道网关的MAC即可.
随后双方即可进行ICMP通信. 显然, 无论是arp请求还是icmp请求, 因为处于trunk端口之间的链路, 均带有vlan id(2).
这里还需要注意, 交换机如何学习MAC地址?
每次交换机在一个端口接收到一个以太帧, 都要先学习帧头的源MAC, 如果该MAC地址在MAC地址表不存在, 记录到MAC地址表, 并启动一个超时定时器.
VLAN间通信
在上述实验中, PC3 显然无法与PC4进行通信; 在本实验中, 我们为S1的Vlan2和Vlan3配置IP, 以使得PC3与PC4之间通信.
1[S1]inter vlan 2
2[S1-Vlanif2]ip address 192.168.2.1 24
3[S1-Vlanif2]inter vlan 3
4[S1-Vlanif3]ip address 192.168.3.1 24
此时, S1充当三层路由器的功能, 因而我们还需要为PC1-4配置默认网关.
为了报文完整, 清理以下PC以及S1(因为作为3层设备所以拥有ARP缓存)arp缓存和两台交换机的mac-address缓存:
1[S1] undo mac-address
2[S1] reset arp all
3
4[S2] undo mac-address
5[PC] arp -d
下面结合抓包情况分析一下PC3 ping PC4时, 报文传递的全过程:
-
PC3将发起icmp请求, 但发现PC4与自己不是一个网段, 因而需要将报文转发给自己的网关; 不过又不知道网关的MAC, 因而PC3第一个报文为请求自己网关MAC地址的ARP报文.
S2从1号Access口收到后, 打上1号端口PVID=2的标记, 因而能够从13号口发出, 由于13号口默认在vlan1, pvid=1, 与报文vlanid不同, 因而不做任何操作, 转发出去.
-
S2收到后, 检查vlan标记为2, 允许接收该ARP请求报文; 随后构造一个同样是vlan2的响应报文(
应该是会这样根据原vlan标记构造响应报文吧), 从13号口发出, 且与13号的PVID不同, 因而不操作标签而直接转发 -
随后S2收到后再转发给1号口, 1号口剔除标签返回给PC3, 至此PC3获得了网关的MAC地址.
-
随后PC3正式发送icmp报文, icmp报文通过S1转发, 打上标记, 到达S1.
-
S1收到该报文后, 却不知道ICMP终点PC4(
3.11
)的MAC地址, 因而通过网关3.1
发起ARP查询; PC4(7d:10
)收到该查询后, 将自己的MAC地址返回给S1.
- 至此, S1可以成功中转PC3发来的icmp请求, 转发到PC4; 再将PC4的响应返回给PC3.
值得注意, S1在5号报文到来时更新自己的mac-address表, 添加PC3的MAC, 再在9号报文到来更新PC4的MAC. (应该是这样, 因为根据源MAC更新地址表)
不过对于ARP缓存表来说, PC是在收到ARP答复后更新自己的缓存表, 那么对于三层的交换机来说呢… 它们会在什么时候更新自己的ARP缓存? 尤其是S1是何时存储PC3的MAC地址?
为了实验, 令PC3 ping一个不存在的地址, 如2.100
或3.100
, 此时PC3拥有S1这个网关的ARP缓存.
快速查看S1的arp缓存, 发现在前几秒钟, S1会有缓存表项3.100
, MAC为Incomplete
, 随后迟迟收不到答复后就认为不存在该地址, 清除了该缓存表项.
再次令PC3 ping 3.100
, 而就在写报告的一会, PC3的ARP缓存失效, 不知道自己的网关在哪里, 会首先发送一个ARP询问2.1
的MAC地址. 尽管此后肯定还是无法访问3.100
, 但是再看S1的ARP缓存, 发现已经存在了PC3的表项.
至此可以基本判明, 对于三层交换机S1而言, 当手下的某个设备通过ARP查询自己时, 才会更新ARP缓存表; 而手下的设备通过ARP查询其他人则不会发生此动作. 尽管唯一的区别在于前者S1会发送一个ARP回复而后者不会, 但也无法判定S1到底是根据什么条件来执行更新缓存表项的动作的, 不过已经得到了一个充分条件, 因而暂且讨论到这里.
OSPF
OSPF不在所选套件的任务范围中, 因而会较详细的学习与分析.
OSPF全称Open Shortest Path First, 是一个基于链路状态算法的内部网关协议. 其核心是每一台路由器都将周边的链路状态描述出来并发送给网络中相邻的路由器; 经过一段时间的交互, 就可以利用最短路有优先算法计算路由.
OSPF通过32bit的区域ID划分区域(area), 相同的区域有相同的拓扑结构数据库; 通过32bit的RouterID来唯一标识一台路由器, 默认是拥有最大IP的Loop地址或是物理接口. 可以说OSPF是接口敏感型的协议。
RFC2328 规定了IPv4采用 OSPF Version 2.
OSPF的配置和使用已经较为熟悉了, 下面主要关注一些理论上的说明.
报文结构与类型
如图所示搭建拓扑结构, 配置回环地址以及OSPF协议.
不太想用自带的debugging模式抓包, 选用wireshark进行分析.
OSPF有5种类型, 拥有相同的报文头, 其结构如下:
其中:
-
type从1到5, 分别表示Hello, DD, LSR, LSU以及LSAck报文
-
length表示OSPF报文的总长度, 包括报文头在内
-
Autype和Authentication是认证类型; 不予说明.
LSA的结构将在链路状态描述详细说明, 这里主要关注五种类型的报文:
- Hello报文. 这是最常用的一种报文, 使用组播地址
224.0.0.5
(链路层协议为Ethernet时默认采用广播类型), 报文中包含一些计时器的数值以及其已知的邻居等.
- DD报文(Database Description). 两个邻居路由器的前两个DD报文为空, 用于确定主从关系, DB Description字段中
Init
置位. 确定完主从关系后, 才发送带有摘要信息的报文, 如下图所示.
- LSR(Link State Request)报文. 路由器之间交换了DD报文后, 通过比较就能知道本地缺少的LSA和需要更新的LSA, 因而发送LSR报文请求所需要的LSA, 报文内容即为请求的LSA的摘要.
- LSU(Link State Update)报文. 用于答复LSR报文, 内容为多条LSA的全部内容.
- LSAck报文. 与DD报文类似, OSPF通过发送和确认的超时重传机制来实现LSA的可靠传输, LSAck就是对LSU报文的确认, 其内容为LSA的首部.
参考:
邻居状态机
书上的这几张图十分清楚, 放上来即可.
需要注意在交互过程中:
-
RT2收到RT1的报文后, 即可将RT1设置为Init状态; 而RT1收到RT2的回复后, 发现存在自己, 即可将RT2设置为Exstart状态. 这里要注意的是, 该状态机是邻居状态机! 是根据报文情况来修改邻居的状态的.
-
RT1发送一个I=1, M=1(More, 表示不是最后一个报文), MS=1(宣称自己是Master), 并规定初始序列号x; RT2收到后修改RT1为ExStart状态, 但由于自身RouterID更加大, 因而将自身MS=1并重新规定了初始序列号y
-
在DD交换过程中, 只有Master会将序列号加1, 而Slave只会携带收到的上一个Master的DD报文的序列号; 通过这种方式双方均可以确认已经收到了对方的报文. 最后设置M=0表示DD交换将要结束.
-
交换完DD后, RT1发现RT2有一些自己没有的LSA, 因而设置RT2为Loading状态, 发起LSR报文请求; 但RT2发现RT1的所有LSA都已经有了, 因而直接设置RT1为Full即可.
至此, 整个报文的交换过程已经较为清楚了.
链路状态描述
OSPF将路由器周边的网络拓扑结构抽象为4种典型的网络结构: Stub net, PPP网络, 点到多点网络以及全连接网络:
-
Stub net. 末端网络, 该网段中没有其他运行OSPF的设备, 只有像计算机这样的设备.
-
PPP: 通过点到点的链路连接到另外一台运行OSPF的路由器.
-
点到多点网络. 通过点到多点的网络连接另外多台OSPF路由器, 但路由器之间彼此并不是全联通的.
-
全连接网络. 存在信息冗余以及$N^2$连接问题.
对每种网络的链路状态描述都可以分为两部分: 对相连网段的描述和对相连路由器的描述; 而每部分又都包含: link id, data, type以及metric四部分.
链路状态描述信息就组成了链路状态通告(LSA)信息, 前三类网络使用第一类LSA描述, 而全连接网络用第二类LSA描述, 更多的使用参见区域划分
LSA的种类
OSPF定义了十一种LSA类型, 这里主要介绍前5种.
LSA结构分析
所有的LSA均拥有相同的LSA头部, 如下所示:
LSA主体中首先为Link Count字段, 后续给出四项信息, 如下所示:
继续分析上述抓到的一个Update报文, 可以看到其中包含两条LSA信息, 分别第一类LSA和第二类LSA.
具体的分析从略, 容易根据上述的理论说明验证其正确性.
指定路由器DR
为了解决全连接网路中的$N^2$问题, OSPF从网络中选举一台路由器DR, 专门负责传递信息; 所有路由器将信息发送给DR, DR再分发给网段内其余路由器. 同时, 考虑到DR由于故障的意外损坏, 会有一个备份路由器BDR与DR同时被选举出来, 也与该网段内所有路由器建立邻居关系并交换路由信息, 用于在DR失效后立即成为DR.
根据Hello报文中的优先级, DR, BDR等字段信息, 选出一个最优的路由器作为DR, 次优的作为BDR. 优先级高的更优, 相同则选择RouterID更大的.
一旦选举完成, 即使后来加入了更优的路由器也不会改变当前的DR, 避免对网络带宽和稳定性的影响.
继续分析上述拓扑结构下的报文. 如下所示, 1.1
成为了DR, 1.2
成为了BDR, 有些出乎意料.
修改拓扑结构如下, 添加S2, 开启S1, S2的三层功能, 所有端口处于VLAN1中并配置IP地址, 启用OSPF.
通过display ospf lsdb [network]
可以看到第二类LSA信息:
LID为R1, 说明其为当前的DR.
通过display ospf peer
可以看到一些更加详细的内容, 如DR以及BDR, 还有各个邻居的状态.
由于S1, S2通过DR来传递消息, 因而二者之间是2way的关系; 但对于DR和BDR则均是Full的状态.
随后我们重启R1的OSPF进程<R1>reset ospf process
, 再次查看S1的ospf peer情况.
此时R2作为BDR立刻接管了DR的地位, 而再次选举出来的BDR也正是拥有最大RouterID的S2.
1<S2>dis route id
2RouterID:168.1.1.4
通过下述debugging指令可以查看详细的OSPF状态转移情况:
1<R1> debugging ospf event
2<R1> terminal debugging
但是太多了所以不予分析了.
区域划分
在大型网络中LSDB会十分庞大, 占用大量的存储空间, 且使得网络带宽利用率变低, 网络容易处于动荡之中.
解决方案主要是通过划分区域, 内部仍然使用一类和二类LSA描述网络, 且仅限于在区域内部传播; 而当ABR收到这类消息后, 会根据域内路由生成一种新的三类LSA, 将其传播到相邻的区域.
第三类的LSA主要对区域内的网段信息进行描述, 内容有网段, 子网掩码, 度量值等. 与一类二类LSA比大大减少了路由描述的数据量.
路由器类型
计算AS外部的路由
ASBR为引入的每一条路由生成五类LSA, 路由信息将在AS内部传播(除了Stub Area), 计算路由时在最短路径树上找到ASBR, 并将其生成的所有五类LSA都当作叶子挂在该ASBR下方.
不过由于划分区域的缘故, 与ASBR不在同一区域的路由器可能无法知道ASBR的确切位置, 因而OSPF规定: 若某区域内有ASBR, 则该区域内的ABR在向其他区域生成路由信息时会单独为该ASBR生成一条四类的LSA, 其内容包含该ASBR的RouterID和花费值.
骨干区域与虚连接
ASR生成三类LSA时, 会将自己的RouterID写到首部, 但当这条LSA传递超过两个区域后, 就会完全失去初始通告路由器的信息, 进而造成路由自环.
OSPF解决的办法是设置一个骨干区域, 0号area. 所有其他区域必须要与骨干区域相连, 且骨干区域自身也必须是联通的. 所有非骨干区域的路由信息封装发给骨干区域, 骨干区域再将信息转发出去. 这样三类LSA信息不会传递超过两个区域, 避免路由自环.
但在实际应用中可能无法满足这些要求, 因而OSPF提出了虚连接的概念. 虚连接是指两台ABR通过一个非骨干区域建立的一条逻辑上的通道, 其两端必须为ABR, 且同时经过配置才可生效. 为两段提供连接的非骨干区域的一条内部路由称为运输区域.
三类报文的分析
建立如下的新拓扑结构:
配置好ospf后, 在R1上输入指令即可查看三类LSA的内容:
1dis ospf lsdb # 所有LSA的概况
2dis ospf lsdb summary # 显示三类的具体内容
这类报文是区域间传递的LSA信息, 由ABR生成, 与一类LSA相比最大的区别在于其描述的内容是网段的路由信息而不是链路状态信息. 此时Ls ID
描述的是目的网络的网络地址.
四类五类报文的分析
四类LSA总是伴随着五类LSA一起产生, 因而这里一起分析.
为了产生这两类的LSA, 需要引入外部路由: 在R1上配置一条静态路由指向S1的Loop1, 并将其引入到OSPF中; 再在S1上配置返回路由:
不知道为何, 静态路由无法配置4.4.4.4 32
的目的地址, 因而修改为4.0
的网段
1[R1]ip route-static 4.4.4.0 24 192.168.1.1
2[R1]ospf
3[R1-ospf-1]import-route static
4[S1]ip route-static 0.0.0.0 0.0.0.0 192.168.1.2
这样配置完成后, 查看R1的OSPF路由表却没有4.0
网段的信息, 但是R2和S2均有了该路由信息…
不过可以通过查看lsa信息:
1dis ospf lsdb ase # 五类LSA
2dis ospf lsdb asbr # 四类LSA
三台设备中都有ase
的信息, 确实收到了来自AS外部的LSA, 其内容稍复杂一些:
E type
取值为1或2, 表示是一类外部路由还是二类外部路由.Forwarding Address
表示去往目的地址的数据应该向哪里转发, 全0意味着想通告路由器ASBR转发即可.Tag
附加信息, 表示外部路由, 但并不直接被ospf协议引用.
而四类LSA结构较为简单一些, 头部的LS ID
为对应的ASBR的RouterID, Adv rtr
为ABR的RouterID.
路由计算
SPF与Cost值
SPF算法一般就是指Dijkstra算法; 每个路由器以自己为根计算出一个最小生成树.
在OSPF中, Cost值=$10^8$/链路带宽, 带宽越高Cost越小.
区域内部的路由计算
每台路由器的lsdb显然是相同的, 在此拓扑结构上以自己为根, 计算MST.
区域间的路由计算
同一个区域内的路由器之间保持LSDB同步, 拓扑结构的变化首先在区域内更新.
区域间的计算则是通过ABR完成, 其首先完成一个区域内的路由计算, 然后为每条OSPF路由都生成一个三类的LSA, 再将这些LSA发送到另一个区域.
另一个区域的路由器根据三类LSA生成路由, 由于都是ABR发布的因而这些路由的下一跳都指向该ABR.
区域外的路由计算
BGP
BGP通告规则
BGP路由注入
BGP报文结构
报文头
OPEN报文
UPDATE报文
NOTIFICATION报文
KEEPALIVE报文
状态转移图
路由聚合
给出拓扑结构:
配置大概如下, 注意next-hop-local
, 后续会分析到.
在R2上查看R1的三个回环地址:
在R1上进行路由聚合:
1[R1-bgp]aggregate 192.168.0.0 23
R2上多出一条路由表项:
重新聚合路由, 不通告具体的细节:
1[R1-bgp]undo aggregate 192.168.0.0 23
2[R1-bgp]aggregate 192.168.0.0 23 detail-suppressed
重新查看R2上的表项, 此时仅有聚合后的一条路由; 当然, 彼此之间可以ping通.
这时R1上删除3号回环地址(192.168.1.1
):
再次观察R2路由表, 发现聚合路由未变化, 仍然能ping通Loop2; 这样有利于网络的稳定.
基本路由属性分析
下面说明一下这常见的几种属性:
- origin: 定义了路径信息的来源, 指示路由更新的来源.
-
AS-Path: 表示经过的AS序列; BGP发言人会将自己的AS前置到AS路径的头部. BGP不接受AS路径中包含本AS号的路由, 因为可能产生路由环路.
-
Next-hop, BGP种的下一跳属性较为复杂, 其可以是下述3种形式之一:
- MED与Local-preference: MED指示进入AS的优先路径(越小优先级越高), 而Local-preference指示出去的较好出口(越大优先级越高)
在上述的拓扑结构中, 为S2添加一个回环地址:
随后将S1和S2的直连路由引入到BGP中:
1[S1-bgp]import-route static
2[S2-bgp]import-route static
关于这一点比较疑惑, 因为并没有通过ip route-static
设置静态路由? 直接通过network
指令说明6.6.6.6
的环回地址需要通告即可?
事实上取消后也并没有说明变化, 不过感觉问题不大, 因而不予深究.
需要说明的是对bgp路由表的分析, 在S1中:
-
第一条表项是S2将EBGP(R2)的路有消息通告给IGBP(S1)的, 本身按照BGP的规则是不修改下一跳的地址的, 但是由于手动设置了
next-hop-local
因而下一跳被设置为了S2的对应接口. -
第二条与第四条表项是EBGP的路由消息, 下一跳是对端接口
-
第三条应该就是IBGP内部的路由, 自然是对端端口地址即可.
路由策略
不是很感兴趣…感觉离的比较远… 不过考试可能会考, 所以看一下
主要学习三种过滤器的设置, 实验拓扑承接上一节.
ACL
在S2上配置过滤, 阻止AS100的5.0.0.0/8
的路由信息传给AS200.
配置规则:
1[S2]acl number 2001
2[S2-acl-basic-2001]rule 0 deny source 5.0.0.0 0.255.255.255
3[S2-acl-basic-2001]rule 1 permit source 0.0.0.0 255.255.255.255
4
5[S2-acl-basic-2001]dis this
6#
7acl number 2001
8 rule 0 deny source 5.0.0.0 0.255.255.255
9 rule 1 permit
10#
11return
应用过滤规则:
1[S2-bgp]peer 2.1.1.2 filter-policy 2001 export
再看R2的路由表, 已经没有了5.5.5.5
网段的信息.
通过wireshark抓到S2向R2发送了两组UPDATE报文:
第二组报文中要求将5.5.5.5
的路由规则移除了, 但是第一条报文中却要求R2移除自己的4.4.4.4
的路由规则, 没搞懂为什么, 也不管了.
AS-Path
在S1上配置过滤, 使得S1不通告来自AS200的路由, 只通告AS300内部的路由.
1[S1]ip as-path-filter 1 deny \b200$
2[S1]ip as-path-filter 1 permit ^$
3
4[S1]bgp 300
5[S1-bgp]peer 1.1.1.1 as-path-filter 1 export
这样, R1上就没有4.4.4.4
的路由信息了.
Route Policy
在S1上配置路由, 使得S1不向外通告6.0.0.0/8
的路由信息, 并且将向外通告的其他路由信息的cost设置为888.
具体操作懒得做了, 这一套本身好像挺复杂了不过实验简单, 考到算倒霉… 贴一下代码, 主要就是对那些匹配上acl的流应用上cost 888
即可.
BGP同步机制
一个BGP路由器不把从IBGP对等体得知的路由信息通告给EBGP, 除非该路由信息也能通过IGP得知, 这就是BGP的同步机制.
下面的例子很生动:
下面说明了BGP与IGP之间的同步关系, 虽然不是很懂, 但是好像有点道理, 并且能解释next-hop-local
的真实用意:
实验比较简单, 就不做了.
组播
组播地址划分
IP地址
组播IP地址的前4bit为1110
, 因而其地址空间为224.0.0.0-239.255.255.255
. 为了合理的利用地址空间, 又在此之上进一步划分(细节可以参考RFC 2365):
224.0.0.0-224.0.0.255
用于网络协议预留, 这些目的地址的报文不会被路由器发送到本地网络之外
-
224.0.1.0-238.255.255.255
用于用户组播地址 -
239.0.0.0-239.255.255.255
用于本地管理组播地址.
MAC地址
48位的MAC地址固定前25位为0x01005e
, 因而只有23位映射到IP上, 而IP除了开头的1110
还有28位, 因而一个组播MAC地址会对应32个组播IP地址, 因而设备驱动或是IP层就必须再对数据包进行过滤.
为何这么设计? 为什么不让MAC与IP一一对应? 留坑
简单的IP组播实验
为了在ensp上测试组播, 需要配置vlc视频播放器, 用于传输一段视频…
这样, 在MCS(MultiCastSource)上启动vlc播放二次元, 在PC2上即可收到.
播放的二次元就不截图了…(大雾)
看一下PC2加入和离开组播组时, 会发送什么报文:
而通过组播源发送的数据是基于UDP的.
IGMP
IGMP是负责IP组播成员管理的协议, 用于在主机与直接相连的路由器之间建立与维护组播成员关系.
素有的IGMP都封装在IP报文中, IP协议号为2, TTL为1以保证旨在本地范围内传送.
IGMP报文结构
IGMP选举过程
为了减少对网络带宽和系统资源的消耗, 有一台专门的IGMP查询器承担发送查询的任务, 在IGMPv2中增加了独立的选举机制:
IGMP加入组
在进程级别:
在网络级别中:
IGMP离开组
IGMP监听
为了避免组播报文向所有端口泛滥, 交换机中内嵌了IGMP Snooping模块, 通过对IGMP报文的分析, 为端口和MAC组播地址建立起映射关系, 根据该关系转发后续的组播数据.
讲的好像很乱..但是大概意思Got, 总体来说就是对转发表信息的维护…后续有实验再仔细分析
IGMP欺骗
IGMP实验
IP组播和IGMP的区别是?
拓扑结构如下:
为R1, R2路由器打开IGMP协议:
1[R2]multicast routing-enable
2[R2]inter g0/0/1
3[R2-GigabitEthernet0/0/1]igmp enable
将PC2加入225.1.1.1
中, 并在路由器端口配上IP地址, 否则端口状态为down
, 莫失莫忘.
随后即可观察到选举过程, 如下图所示:
- R1(
1.1
)和R2(1.3
)启动后都会发起一个普遍组查询报文, 但随后R2落选, 每次都是R1发送组查询报文, PC2进行回应.
- 在路由器的控制台中通过
dis igmp inter
可以查看到IGMP的查询器, 同时也能看到默认查询间隔为60s, 这也与上述报文中的间隔相同.
下面观察主机加入以及离开组时路由器的动作:
-
当PC{1,2,3}均已加入各自的组后, 令PC1离开,
R1会向该组发起一个查询, 尚存的PC3会报告组内仍然有成员, 但是为何PC2也会进行一次响应?… 明明报告的组播组地址以及查询的报文均与PC2无关?…
怀疑是PC2错误地不知道在什么时候加入了239组, 因而强迫PC2离开一次该组:
这样问题就解决了, 看来确实是不知道这么回事PC2进入了239组, 并且向外报告自己是225的人.
但是当我尝试将PC2离开225组后, 好像发现了真正的问题所在:
-
239.1.1.1
和225.1.1.1
的在MAC地址级别是相同的! 无需分析二进制, 只需想到: 前4位固定1110, 而又有5位丢失, 那么低24位若是相同, 高8位无论多少都一定对应着相同的MAC地址. 因而,225
组的PC2确实会报告针对239
的查询报文. -
那么, 为什么当强迫PC2离开
239
后, 再次发起查询就没有PC2了呢? 事实上, 这样操作后, 在一段时间内确实PC2就不会响应针对239
的报文查询了, 但是一段时间过后又会照常响应. 那么肯定是cache之类的超时了, 这里首先怀疑是交换机的监听功能. 因而监听PC2-S1
与S1-R1
之间的报文, 发现完全一样, 这说明S1没有偷偷地过滤掉一些报文; 那么问题可能就出在PC的IP/MAC模块了, 不过好像无从考证, 就不一探究竟了.
-
-
当PC1已经离开, PC{2,3}仍然在各自组中时, 令PC2离开:
路由器焦急地查询了两次, 但是已经没有
225
组中的成员了没有人对其响应; 计时器超时后, R1就不再维护该组的信息了. -
将PC2返回组播组, 通过
dis igmp group
可以查看R1的igmp组情况:
PIM-DM
组播协议主要包括IGMP和组播路由协议; 想要在实际网络中实现组播数据包的转发, 必须要在互联设备上运行组播路由协议. 下面主要介绍两种域内组播路由协议: PIM-DM与PIM-SM.
RPF检查
逆向路径转发(Reverse Path Forwarding, RPF)检查:
PIM-DM报文结构
PIM协议中Register, Register-Stop, Graft, Graft-ACK报文为单薄发送, 其余的所有报文均为组播发送, 目的地址为224.0.0.13
, 表示所有的PIM路由器.
DM主要有以下几种报文:
- Hello报文. 用于PIM邻居的发现, 保活, 同时也会协商PIM的相关参数.
-
Join/Prune报文. Join报文用于加入组播分发树,Prune用于修剪组播分发树.
-
Graft/Graft-ACK报文. 用于通告上游路由器加入组播分发树.
- Assert报文. 用于断言机制, 当一个网络中有多个PIM可以发送组播流量时, 断言机制可以使得所有的组播路由器选举出一个路由器发送组播流量.
PIM-DM扩散与剪枝
PIM-DM嫁接
PIM-DM剪枝否决
PIM-DM断言机制
PIM-DM转发机制
PIM-DM实验
配置如下拓扑结构, 在R1, S1, R2上配置OSPF使得全网互通, S2只作为二层设备, 配置VLAN即可.
在三层设备上配置组播路由协议:
1[S1]multicast routing-enable
2[S1]inter vlan 2
3[S1-Vlanif2]pim dm
4[S1-Vlanif2]inter vlan 3
5[S1-Vlanif3]pim dm
6[S1-Vlanif3]inter vlan 4
7[S1-Vlanif4]pim dm
随后可以看到PIM邻居的情况:
为S1与R1, S1与R2之间相连的接口关闭pim state-refresh
功能, 以清楚地看到扩散剪枝以及否决等过程(为啥?不知道):
1[S1]inter vlan 3
2[S1-Vlanif3]undo pim state-refresh-capable
3[S1-Vlanif3]inter vlan 4
4[S1-Vlanif4]undo pim state-refresh-capable
5
6[R1-GigabitEthernet0/0/0]undo pim st
7[R1-GigabitEthernet0/0/0]undo pim state-refresh-capable
8
9[R2-GigabitEthernet0/0/0]undo pim state-
10[R2-GigabitEthernet0/0/0]undo pim state-refresh-capable
在禁用前, PIM有时候会偷偷发一些State-Refresh
报文.
在PIM-DM网络中,为了避免被裁剪的接口因为“剪枝定时器”超时而恢复转发,离组播源最近的第一跳路由器会周期性地触发State Refresh报文在全网内扩散。收到State Refresh报文的PIM路由器会刷新剪枝定时器的状态。被裁剪接口的下游叶子路由器如果一直没有组成员加入,该接口将一直处于抑制转发状态。
在边缘的三层设备上启用IGMP:
1[S1-Vlanif4]inter vlan 2
2[S1-Vlanif2]igmp enable
3
4[R2-GigabitEthernet0/0/0]inter g0/0/1
5[R2-GigabitEthernet0/0/1]igmp enable
扩散与剪枝
错误, 胡扯.随后, 启动组播源, 开始组播二次元; 此时不启动PC1. 因而R1, R2下游均没有可用的组成员, 即将进行prune剪枝. 察觉到有两条剪枝报文, 一条是S1下游即R2对应的接口的剪枝消息, 因为R2发现自己没有任何需要组播的成员; 此后该连路上还会有若干的UDP报文, 在此之间的一段时间, S1也发现了自己在该端口没有组播成员, 因而S1的端口又发送了一次剪枝消息, 自此该链路上没有任何UDP报文了.
需要勘误的地方是, 并不是哪个接口发Prune就意味着某个接口要发起剪枝!
因为细看prune报文, 其中PIM Options中有明确提到上游邻居的IP地址的, 而且prune是向上游接口发送的, 之前的分析都是在胡扯什么… 但是也有一些奇怪的地方, 比如有时候上游接口自己还会发一个通知自己的prune报文… 比如这里就是, 因而导致了我最初的错误理解, 这个问题还没有解决. 一种猜测是, 出现了OSPF的DR什么的? 然后DR对报文又转发了一次吗…不管了, 学习知识是螺旋上升的.
进入其中一个报文细看:
都比较容易理解, 其中IP address
表示该地址发来的组播报文无需再转发.
在S1中通过查看pim routing-table
以及pim routing-table fsm
可以看到路由情况以及剪枝情况:
当210s的计时器超时后, 被剪枝的接口又被加回到出接口中, 数据流再次得到发送:
此时, 组播数据流处于扩散时期, 但是却没有观察到第二次的剪枝发生, 大量的UDP涌来…只能在后台关闭了二次元的组播. 不是很明白为何看不到二次剪枝, 暂时不管了.
嫁接与ACK
在210s内, 令PC1加入239
组, 发现Graft以及Graft-ACK报文:
可以清晰地看到这两个报文的细节结构.
RPF与有源树
下面考察RPF转发以及有源树, 修改拓扑结构如下, 其中S3仅仅做二层转发:
有源树是怎么构造出来的呢? 目前的理解是, 根据Assert机制和ospf生成树综合生成出来的.
并且存在一些疑问, 只能做出如下假设:
-
在pim routing表中, (*, G)不会影响(S, G)表项.
-
如果路由器接收到了一个组播报文, 且自己的(S, G)表项为空, 那么该路由器是有可能仅仅只是通知CPU创建(S, G)这一对地址的表项, 而具体是否要转发这条报文还要通过RPF判断才行.
以该拓扑结构为例, 不修改任何一条链路的ospf值, 那么在OSPF路由表中S2通过10.2.1.1
下一跳到达MCS1, R2通过也10.2.1.1
下一跳到达MCS1, 而R1就比较特殊了, 查看R1的OSPF routing表:
我们发现, R1有若干条去往同一目的地但是OSPF cost相等的路由, 那么应该如何如何决定呢?… 如何处理cost相同的路由可能有标准定义过了, 但是网上粗略的找了一下发现没有什么, 因而也可能是厂家自定义的. 这里可能可以通过若干证据来说明是优先走的NextHop更大的接口: (证据1)在路由表中排名更前, (证据2)tracert的结果:
因而这边认为R1到MCS1的下一跳是R2.
因而, 在上述的条件下, 我们认为R1与S2之间的链路可能会发生assert机制. R1将R2发来的报文发出, S2将S1发来的报文发出, 双方的端口彼此收到了对方发来的同样的报文, 因而需要assert来选举.
通过dis pim routing fsm
确实可以看到, 在该链路上爆发了assert的争夺, 然后S2的端口获胜(W), 而R1的失败(L).
发起组播, 但是PC{1,2,3}不打开vlc, 只是令MCS发起组播; 用wireshark对S1-S2-R1-R2-S1这四条链路进行抓包, 分别记为1,2,3,4号链路.
结果是:
-
1号与4号链路上只有hello, 应该是正常的
-
(错误理解) 2号链路可以看到
10.4.1.2
与10.4.1.1
的assert争夺, 而当assert定胜负后, 先由10.4.1.2
发起一次prune报文, 随后能看到10.4.1.1
发起一次prune, 这里或许有问题? 因为PC2也在10.4.1.1
网段上, 或许是因为为了偷懒没有打开客户端的vlc, 导致认为客户端不存在?
- (错误理解) 3号链路上收到两条剪枝报文, 第一条来自于
10.5.1.2
, 第二条来自于10.5.1.1
, 第一条容易理解, 因为R1争夺assert失败了, 没有可用的下游端口了, 第二条的产生可能说明了客户端确实要打开vlc才行…
重新尝试一下, 为了pim routing不被缓存污染, 需要静置一段时间后再进行实验; 出人意料的是, 结果并未有任何改变, 但确实是在情理之中: 因为几台PC都已经加入了239
的组播组, 确实能够接收到对应的报文, 只是没有VLC启用端口来对报文进行处理(播放视频)罢了. 因而需要重新考虑原因.
事实上, 注意到剪枝(prune)报文通常是向上游来通告自己不行了, 加上其中包含了上游邻居的IP, 因而重新考察截获的报文:
-
2号链路上的prune全部都是通告
10.4.1.1
的剪枝报文, 这是正确的, 因为R1没有需要转发组播报文. -
3号链路上的两条prune都是通告
10.5.1.1
的剪枝, 这其实就很奇怪了… 到这里的话, 问题在于PC3是如何通告R2自己需要组播报文呢? 一种猜测是通过(*, G)的表项, 但是真的.. 不知道咋弄了, 螺旋上升吧.
令S2与R1之间的OSPF Cost为100:
1[S2] inter vlan 4
2[S2-Vlanif4]ospf cost 100
3
4[R1] inter g0/0/0
5[R1-GigabitEthernet0/0/0]ospf cost 100
组播源开始组播二次元, PC{1,2,3}同时打开接收, 展示出4台PIM-DM设备的PIM路由表:
根据对4台设备的路由情况进行分析可知, R1此时已被架空, 流量优先从其余的设备进行组播.
取消S2-R1之间的高cost, 修改为S1-S2之间拥有高cost, 再次组播二次元, 可以发现路径发生了改变, 变为了: S1-R2-R1-S2-PC.
好像就是根据有源树来决定是不是RPF接口什么的, 但是在wireshark中好像也看不到太多的现象. 因而暂且不管.
事实上, 在这种情况下PC2是收获不到报文的, 这就是RPF判断的结果. 因为从Vlan4已经获得了上游的组播报文, 因而尽管PC2也处于Vlan4, 但是S2不会向PC2转发报文了, 将高ospf删除后有源树结构改变, Vlan4不再是上游, 即可恢复正常.
下面考察Assert的实验(此时, 无高cost值). 可以通过dis pim routing fsm
看到选举的结果.
fsm
展示的比较详细全面, 可以看到, 在一对(S, G)
表项下会将所有的接口分为下游接口和非下游接口, 非下游接口会有winner
字段, 这应该就说明了assert机制反应的作用: 非下游接口只会接收winner发送来的报文.
疑问在于, 根据上述的4个路由表可以得知此时的组播树, 但是好像不存在什么拓扑结构下涉及到2个组播源同时发送, 那么在链路中还是能抓包收到一些assert的报文. 这些assert是为何会产生呢? 又有什么作用呢? 只能留坑, 这边折腾了太久了
后记, 根据上述的fsm显示, 发现S1与R2竟然也产生了一段assert竞争?? 这过于奇怪了, 比较怀疑是缓存没有清理干净, 这里保留上述的实验结果.
剪枝否决
最后观察一下剪枝否决的现象. 为了实现, 应该要使得S1-S2的高ospf值存在, 然后在PC{1,3}之间实验, 这样R{1,2}会进行剪枝与否决的动作.
遗憾的是, 并做不出来. 令某一台PC(如PC1)关闭VLC后, 会得到一条剪枝报文, 但是好像就是不太行, 剪了后PC3还是能正常播放二次元. pim routing-table
也非常的好, 完全的不解… 但是居然好像每次都会出现graft? …
后记, graft可能只是超时计时器到了后, 再将下游接口graft回去… 不启用S1-S2的高cost值也做不出来, 此时S2和R2应该会再S1的vlan3上发生剪枝否决; 但是也做不出来, 原因是R2发送的剪枝报文(目的地址为224.0.0.13
, 所有的pim路由器), S1并不向G0/0/13口转发, 直接吞掉了, 那么S2又怎么会去否决呢? … 不知道是谁的原因, 但感觉对大部分原理已经有些了解了, 就不去细究了吧.
修改拓朴结构如下:
这样就比较好看到剪枝否决了, 当正常组播进行时, PC2退出组播, 发出一个prune, R2收到后会着急地发送一个join回去, 这样组播数据流又会照常继续.
参考资料:
PIM-SM
跑步进入PIM-SM吧! DM的各种问题弄了太久时间了, 可能弄了一两天, 实验也做了特别多, 但是仍然有许多未解之谜…
PIM-SM基本原理
PIM-SM选举DR
PIM-SM指定汇聚点RP
PIM-SM构建共享树RPT
rpt的建立总体来说就比较简单了, 其随着成员加入组播组而一并建成. 当成员加入组后, 通过igmp通知dr, dr再倒着向rp发报文, 一路建边, 当rp发送组播报文时顺着这条路即可; 删除同理.
PIM-SM组播源注册与取消
PIM-SM从RPT到SPT
如果没有理解错, 低速率下是: 组播源 - 直连 - DR - SPT - RP - RPT - DP - 直连 - 接收方, 这样在拆除时要同时完成SPT与RPT的拆除.
PIM-SM断言机制
与PIM-DM类似, 不予赘述
PIM-SM实验
基本配置
拓扑结构如下所示:
为四台设备相应的端口开启pim sm
, 再只令R1一人加入候选bsr与rp, 这样R1就一定是bsr与rp了:
1[R1]pim
2[R1-pim]dis this
3[V200R003C00]
4#
5pim
6 c-bsr hash-length 4
7 c-bsr GigabitEthernet0/0/0
8 c-rp GigabitEthernet0/0/0
9#
10return
再在边缘路由器上开启IGMP, 这里是针对PC2, 即R2的G0/0/1与S2的vlan3, 不需要为S1设置IGMP支持(为啥.)
通过dis pim rp-info
可以看到rp的选举情况.
也抓了一个bootstrap的报文. 不过没有看到candidate bootstrap? 不知道为什么. 按道理应该会汇聚到bsr这边再统一发送? 不过能看到R1的两个端口一直周期地往外发送bootstrap通告全网. 到底为啥需要更多的实验作证, 留坑.
RPT与SPT
下面将PC2加入组, 可以看到S2, R2的pim路由表非常的对, 一路延申到R1, R1再无上游接口了, 因为RPT树已经到根了.
启动mcs1发送组播, 路由路径却变成了S1->S2->R2, 这是由于默认的切换阈值为0, R2一旦收到组播报文就从RPT切换为了SPT, 以S2路由表为例:
可以看到确实好像是进行了转变. 为了修改阈值, 在R2上修改:
1[S2]pim
2[S2-pim]spt-switch-threshold infinity
这样, R1就切实地充当了RP转发的功能.
在R1,S2,R2上由于RPT的建立会每人拥有一条(*, G)的表项; 而在在S1与R1上又会由于组播源注册的原因每人拥有一条(S, G)的表项, 如下所示:
这应该是由于组播源通过发送register报文给RP, 它会在一路上会创建一条SPT路径.
组播源注册
当组播源播放二次元时, 会向RP发送Register报文, 但若组播组没有成员存在, RP会返回Register-Stop报文, 以阻止组播源发送报文; 此后组播源也会定期发送注册消息:
前面一坨Register报文中均封装了数据, 因而导致了checksum不对; 但后面的定期查询则没有封装数据, 里面只有前四层的报文内容.
不过当我将PC2加入到239组中却也并未发现register报文, 而是一旦加入后, R1竟向S1发送一次join报文, 随后就开始倾泻UDP数据了…
这与所想的好像有些差异, 因为按照前面的说明, 这一对报文应该只需要发送一次来建立SPT即可, 那么怎么会又有这种周期性的现象以及抑制S1转发组播报文的功能呢?
可能可以参考华为的这个文档NE20E-S V800R010C10SPC500 特性描述 - IP组播 01
其中提到, 当组播源活跃时, DR会向RP发送Register, 并且:
在注册抑制期间,DR向RP发送“空注册消息”,通告组播源仍处于激活状态;注册抑制超时后,DR重新使用Register注册消息封装组播数据报文。在“空注册消息”中,Multicast data packet字段只包含组播数据报文的IP头:组播源地址和组地址等。
而Register-Stop报文会在三种情况下发送:
- 接收者不再通过RP接收发往某组播组的数据
- RP不再为某组播组服务
- 组播数据转发路径已经由RPT(Rendezvous Point Tree)切换到SPT(Shortest Path Tree)
组播源端DR收到Register-Stop消息后,停止使用Register注册消息封装组播数据报文,并进入注册抑制状态。
以及:
一个Register-Stop消息中只能携带一项(S,G)信息。当RP向源端DR发送一个Register-Stop消息,只能结束一项(S,G)注册。源端DR收到携带(S,G)信息的Register-Stop消息后,只停止(S,G)报文的封装。源S向其他组播组发出的报文仍然使用Register消息封装。
猜测: 那么问题可能就是, 除了开头那一大串的register和stop, 后续的定期register对其实就是对链路关系的维护而已, 并不涉及到spt的建立了; 而一旦join报文的到来, 立刻使得S1退出抑制关系, 开始利用先前建立的spt链路, 开始发udp数据.
这样说来, 不应该先令组播源空组播出去, 这时可能已经建立起来了spt路径; 应该先令PC2加入到239组中, 再令组播源开始组播, 这样可能就可以看到前几个封装了数据的register报文了:
确实! 这样确实能看到前几个封装了数据的报文, 且可以较高的概率确信, 这些register对的用处就是建立spt树.
而当停止组播后, 也能定期收到register对, 这时应该认为它们的作用是保活了; 此后若是收到了Join报文, 立刻就可以利用起这些链路来.
BSR与RP的选举过程
添加R2 G0/0/1也为候选BSR, 并分配更高的优先级为1(默认为0).
1[R2-pim]c-bsr g0/0/1 4 1
2[R2-pim]dis this
3[V200R003C00]
4#
5pim
6 c-bsr hash-length 4
7 c-bsr priority 1
8 c-bsr GigabitEthernet0/0/1
9 spt-switch-threshold infinity
10#
11return
这样, R2就成为了BSR, 并且可以看到候选RP通告报文了:
这些报文确实是发给了bsr, 但是bootstrap报文好像每个路由器都会产生, 通告到整个PIM-SM域的信息, 通过对每条链路抓包, 发现以下接口都会发送Bootstrap报文:
-
R2 G0/0/0
-
S2 inter vlan 2, inter vlan 4
-
R1 G0/0/0
-
S1 inter vlan 4
如果除去RP(R1 G0/0/0)本身, 确实整个网络都被不重不漏的覆盖了… 好神秘啊… 螺旋上升吧
同样参考华为的文档:
当PIM-SM网络中使用动态RP时,配置了C-BSR(Candidate-BootStrap Router)的路由器从所有PIM接口周期性的发送Bootstrap消息,参与BSR竞选。竞选获胜者,继续发送Bootstrap消息,向域内所有PIM设备发布RP-Set信息。
可以看一下设备上这几个路由器都默认有c-bsr的配置… 留坑
一个网络中有且仅有一个BSR, 但是RP可以有多个, 可以参考下述的实验, 懒得做了: