Open vSwitch STP

本文主要介绍 Open vSwitch 中 STP 的应用。

我的新书《LangChain编程从入门到实践》 已经开售!推荐正在学习AI应用开发的朋友购买阅读!
LangChain编程从入门到实践

STP 生成树协议

STP 协议通过在逻辑上将特定的端口进行阻塞,从而解决网络中存在的二层环路问题同时使网络在二层物理链路中存在冗余;
未命名文件.jpg

二层交换机的转发机制

交换机对于从一个 port N 上 incoming frame,学习其 source MAC X,生成 MAC Address Table,比如MAC X <------> Port N 生成 MAC 地址和 Port 的映射表。如果收到下一个 frame ,就会查询 frame 的 MAC 与 MAC Address Table 进行匹配,匹配到了就从对应的 Port 发送出去。如果没有匹配到,就认为是 unknown unicast 或 broadcast,没有办法只好把它从所有 Port ( 除了接收到 frame 的接口)发送出去,到了另外一台交换机也是这么处理,于是这个 frame 就一直在封闭的环路里无限的循环。

生成树 Spanning Tree

用一种逻辑的方法将物理的环路斩断,斩成一个发散的树状架构,解决 frame 无限循环下去的问题,如果把树的拓扑结构用于二层交换网络,在二层网络里选择一个根(root bridge),其它交换机当作树的树杈,每个树杈自然有一个根末梢(root port),这个就是交换机的上游接口,其它的接口都是下游接口,至于下游接口是畅通的、还是阻断的,取决于到根的路径成本 cost,谁更接近根,谁就畅通(forwarding) ,即 designated port;谁远离根,谁就需要被阻断(blocked), 即常说的 non designated Port。通过这种仿生的机制,可以有效地避免网络环路。
每个广播域中选举一个根桥(Root)
每个非根桥选举一个根端口(Root Port)
每一段链路选举一个指定端口(Designated Port)
非指定端口会被阻塞(Blocking)

环路问题确定

网络环路可分为网络二层和三层环路,首先看 IP 头中的 IPID 标识,如果数据包中的 IPID 都一样,可判断存在网络环路。再看 IP 头中的 TTL 值,若数据包中的 TTL 值逐渐减 1,可判断存在网络三层环路,即网络路由环路,需检查网络中的路由。若 TTL 值一直没变,可判断存在网络二层环路,需检查网络中的二层设备。

OvS STP

创建网络拓扑
network-topo.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
ip netns add ns1
ovs-vsctl add-br br1
ovs-vsctl add-port br1 tap1 -- set Interface tap1 type=internal
ip link set tap1 netns ns1
ip netns exec ns1 ip addr add 1.1.1.1/24 dev tap1
ip netns exec ns1 ip link set tap1 up

ip netns add ns2
ovs-vsctl add-br br2
ovs-vsctl add-port br2 tap2 -- set Interface tap2 type=internal
ip link set tap2 netns ns2
ip netns exec ns2 ip addr add 1.1.1.2/24 dev tap2
ip netns exec ns2 ip link set tap2 up

ip netns add ns3
ovs-vsctl add-br br3
ovs-vsctl add-port br3 tap3 -- set Interface tap3 type=internal
ip link set tap3 netns ns3
ip netns exec ns3 ip addr add 1.1.1.3/24 dev tap3
ip netns exec ns3 ip link set tap3 up


ip link add br1-br2 type veth peer name br2-br1
ip link add br1-br3 type veth peer name br3-br1
ip link add br2-br3 type veth peer name br3-br2

ip link set dev br1-br2 up
ip link set dev br2-br1 up
ip link set dev br1-br3 up
ip link set dev br3-br1 up
ip link set dev br2-br3 up
ip link set dev br3-br2 up

# 连接 br1 <-> br2
ovs-vsctl add-port br1 br1-br2
ovs-vsctl add-port br2 br2-br1

# 连接 br1 <-> br3
ovs-vsctl add-port br1 br1-br3
ovs-vsctl add-port br3 br3-br1

# 连接 br2 <-> br3 一半,故还未组成环路
ovs-vsctl add-port br2 br2-br3
  1. 连通测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ ip netns exec ns1 ping -c 3 1.1.1.2
    PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
    64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=1.35 ms
    64 bytes from 1.1.1.2: icmp_seq=2 ttl=64 time=0.120 ms
    64 bytes from 1.1.1.2: icmp_seq=3 ttl=64 time=0.111 ms

    --- 1.1.1.2 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2006ms
    rtt min/avg/max/mdev = 0.111/0.529/1.358/0.586 ms
    $ ip netns exec ns1 ping -c 3 1.1.1.3
    PING 1.1.1.3 (1.1.1.3) 56(84) bytes of data.
    64 bytes from 1.1.1.3: icmp_seq=1 ttl=64 time=1.43 ms
    64 bytes from 1.1.1.3: icmp_seq=2 ttl=64 time=0.121 ms
    64 bytes from 1.1.1.3: icmp_seq=3 ttl=64 time=0.150 ms

    --- 1.1.1.3 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2006ms
    rtt min/avg/max/mdev = 0.121/0.569/1.436/0.613 ms
  2. br2 和 br3 连通组成二层环路
    ovs-vsctl add-port br3 br3-br2

  3. 环路后进行连通性测试,结果时通时不通

    1
    2
    3
    4
    5
    6
    7
    $ ip netns exec ns1 ping -c 3 1.1.1.2
    PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
    64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=1.21 ms

    --- 1.1.1.2 ping statistics ---
    3 packets transmitted, 1 received, 66% packet loss, time 2002ms
    rtt min/avg/max/mdev = 1.211/1.211/1.211/0.000 ms

环路情况下分析

  1. 查询端口名称和索引的对应关系

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ ovs-ofctl show br1
    1(tap1): addr:00:00:00:00:00:00
    2(br1-br2): addr:16:ea:56:83:dc:bb
    3(br1-br3): addr:96:53:db:b9:6d:7d

    $ ovs-ofctl show br2
    1(tap2): addr:00:00:00:00:00:00
    2(br2-br1): addr:22:22:47:4f:ce:cb
    3(br2-br3): addr:16:65:81:9b:d1:c7

    $ ovs-ofctl show br3
    1(tap3): addr:00:00:00:00:00:00
    2(br3-br1): addr:ce:ef:8d:5f:a6:e2
    3(br3-br2): addr:16:9a:85:2e:07:76
  2. 查看 ns1 的 arp 表项,发现已经无法学习到 1.1.1.3 MAC 地址

    1
    2
    3
    4
    ip netns exec ns1 arp -n
    地址 类型 硬件地址 标志 Mask 接口
    1.1.1.3 (incomplete) tap1
    1.1.1.2 ether 5e:d8:35:40:0e:a5 C tap1
  3. 分别查看 br1、br2、br3 的 MAC 转发表均发生错乱,br1 连接 ns1 的 tap1,br2 连接 ns2 的 tap2,br3 连接 ns3 的 tap3 本应该分别从各自的接口 1 学习到

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $ ovs-appctl fdb/show br1
    port VLAN MAC Age
    ...
    3 0 5e:d8:35:40:0e:a5 0
    3 0 1a:0d:61:8b:4c:5d 0
    2 0 ca:d4:37:41:f5:c5 0

    $ ovs-appctl fdb/show br2
    port VLAN MAC Age
    ...
    3 0 1a:0d:61:8b:4c:5d 0
    3 0 5e:d8:35:40:0e:a5 0
    3 0 ca:d4:37:41:f5:c5 0

    $ ovs-appctl fdb/show br3
    port VLAN MAC Age
    ...
    2 0 5e:d8:35:40:0e:a5 0
    2 0 1a:0d:61:8b:4c:5d 0
    3 0 ca:d4:37:41:f5:c5 0

开启 ovs stp

  1. 开启 stp

    1
    2
    3
    ovs-vsctl set Bridge br1 stp_enable=true
    ovs-vsctl set Bridge br2 stp_enable=true
    ovs-vsctl set Bridge br3 stp_enable=true
  2. stp 研究

    1
    2
    3
    4
    $ ovs-vsctl list bridge
    br1: stp_root_path_cost="2"
    br2: stp_root_path_cost="0"
    br3: stp_root_path_cost="2"

    stp_root_path_cost可知,已经被逻辑修剪为如下拓扑图
    network-topo.png

  3. ns2 ping ns3,并在 br1-br3 处抓包

    1
    2
    3
    4
    5
    $ ip netns exec ns2 ping -c 2 1.1.1.3
    PING 1.1.1.3 (1.1.1.3) 56(84) bytes of data.
    64 bytes from 1.1.1.3: icmp_seq=1 ttl=64 time=1.48 ms
    64 bytes from 1.1.1.3: icmp_seq=2 ttl=64 time=0.160 ms
    ...
    1
    2
    3
    4
    5
    6
    $ tcpdump -i br1-br3
    ...
    21:24:44.806469 IP 1.1.1.2 > 1.1.1.3: ICMP echo request, id 20724, seq 1, length 64
    21:24:44.806531 IP 1.1.1.3 > 1.1.1.2: ICMP echo reply, id 20724, seq 1, length 64
    21:24:45.807056 IP 1.1.1.2 > 1.1.1.3: ICMP echo request, id 20724, seq 2, length 64
    21:24:45.807104 IP 1.1.1.3 > 1.1.1.2: ICMP echo reply, id 20724, seq 2, length 64

    由抓取结果可知,报文流量经过了 br1,可确定 ovs 二层环路问题已解决。

清除实验环境

1
2
3
4
5
6
7
8
9
ip link  del br1-br2 type veth peer name br2-br1
ip link del br1-br3 type veth peer name br3-br1
ip link del br2-br3 type veth peer name br3-br2
ovs-vsctl del-br br1
ovs-vsctl del-br br2
ovs-vsctl del-br br3
ip netns del ns1
ip netns del ns2
ip netns del ns3

stp 相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 开启 br1 stp
ovs-vsctl set bridge br1 tp_enable=ture

# 关闭 br1 stp
ovs-vsctl set bridge br1 stp_enable=false

# 设置 br1 stp cost
ovs-vsctl set port br2-br1 other_config:stp-path-cost=100

# 查询 br1 stp 状态
ovs-vsctl get bridge br1 stp_enable

# 设置 br1 的 stp 优先级
ovs-vsctl set bridge br1 other_config:stp-priority=0x7800

# 移除 br1 stp 设置
ovs-vsctl clear bridge br1 other_config

参考链接

如何理解STP生成树协议?

作者

莫尔索

发布于

2020-06-14

更新于

2024-05-24

许可协议

评论