Open vSwitch 中 STP

https://morsoli.com/uncategorized/ovs-stp.html

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

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. ip netns add ns1
  2. ovs-vsctl add-br br1
  3. ovs-vsctl add-port br1 tap1 -- set Interface tap1 type=internal
  4. ip link set tap1 netns ns1
  5. ip netns exec ns1 ip addr add 1.1.1.1/24 dev tap1
  6. ip netns exec ns1 ip link set tap1 up
  7. ip netns add ns2
  8. ovs-vsctl add-br br2
  9. ovs-vsctl add-port br2 tap2 -- set Interface tap2 type=internal
  10. ip link set tap2 netns ns2
  11. ip netns exec ns2 ip addr add 1.1.1.2/24 dev tap2
  12. ip netns exec ns2 ip link set tap2 up
  13. ip netns add ns3
  14. ovs-vsctl add-br br3
  15. ovs-vsctl add-port br3 tap3 -- set Interface tap3 type=internal
  16. ip link set tap3 netns ns3
  17. ip netns exec ns3 ip addr add 1.1.1.3/24 dev tap3
  18. ip netns exec ns3 ip link set tap3 up
  19. ip link add br1-br2 type veth peer name br2-br1
  20. ip link add br1-br3 type veth peer name br3-br1
  21. ip link add br2-br3 type veth peer name br3-br2
  22. ip link set dev br1-br2 up
  23. ip link set dev br2-br1 up
  24. ip link set dev br1-br3 up
  25. ip link set dev br3-br1 up
  26. ip link set dev br2-br3 up
  27. ip link set dev br3-br2 up
  28. # 连接 br1 <-> br2
  29. ovs-vsctl add-port br1 br1-br2
  30. ovs-vsctl add-port br2 br2-br1
  31. # 连接 br1 <-> br3
  32. ovs-vsctl add-port br1 br1-br3
  33. ovs-vsctl add-port br3 br3-br1
  34. # 连接 br2 <-> br3 一半,故还未组成环路
  35. ovs-vsctl add-port br2 br2-br3
  1. 连通测试

    1. $ ip netns exec ns1 ping -c 3 1.1.1.2
    2. PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
    3. 64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=1.35 ms
    4. 64 bytes from 1.1.1.2: icmp_seq=2 ttl=64 time=0.120 ms
    5. 64 bytes from 1.1.1.2: icmp_seq=3 ttl=64 time=0.111 ms
    6. --- 1.1.1.2 ping statistics ---
    7. 3 packets transmitted, 3 received, 0% packet loss, time 2006ms
    8. rtt min/avg/max/mdev = 0.111/0.529/1.358/0.586 ms
    9. $ ip netns exec ns1 ping -c 3 1.1.1.3
    10. PING 1.1.1.3 (1.1.1.3) 56(84) bytes of data.
    11. 64 bytes from 1.1.1.3: icmp_seq=1 ttl=64 time=1.43 ms
    12. 64 bytes from 1.1.1.3: icmp_seq=2 ttl=64 time=0.121 ms
    13. 64 bytes from 1.1.1.3: icmp_seq=3 ttl=64 time=0.150 ms
    14. --- 1.1.1.3 ping statistics ---
    15. 3 packets transmitted, 3 received, 0% packet loss, time 2006ms
    16. 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. $ ip netns exec ns1 ping -c 3 1.1.1.2
    2. PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
    3. 64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=1.21 ms
    4. --- 1.1.1.2 ping statistics ---
    5. 3 packets transmitted, 1 received, 66% packet loss, time 2002ms
    6. rtt min/avg/max/mdev = 1.211/1.211/1.211/0.000 ms

环路情况下分析

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

    1. $ ovs-ofctl show br1
    2. 1(tap1): addr:00:00:00:00:00:00
    3. 2(br1-br2): addr:16:ea:56:83:dc:bb
    4. 3(br1-br3): addr:96:53:db:b9:6d:7d
    5. $ ovs-ofctl show br2
    6. 1(tap2): addr:00:00:00:00:00:00
    7. 2(br2-br1): addr:22:22:47:4f:ce:cb
    8. 3(br2-br3): addr:16:65:81:9b:d1:c7
    9. $ ovs-ofctl show br3
    10. 1(tap3): addr:00:00:00:00:00:00
    11. 2(br3-br1): addr:ce:ef:8d:5f:a6:e2
    12. 3(br3-br2): addr:16:9a:85:2e:07:76
  2. 查看 ns1 的 arp 表项,发现已经无法学习到 1.1.1.3 MAC 地址

    1. ip netns exec ns1 arp -n
    2. 地址 类型 硬件地址 标志 Mask 接口
    3. 1.1.1.3 (incomplete) tap1
    4. 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. $ ovs-appctl fdb/show br1
    2. port VLAN MAC Age
    3. ...
    4. 3 0 5e:d8:35:40:0e:a5 0
    5. 3 0 1a:0d:61:8b:4c:5d 0
    6. 2 0 ca:d4:37:41:f5:c5 0
    7. $ ovs-appctl fdb/show br2
    8. port VLAN MAC Age
    9. ...
    10. 3 0 1a:0d:61:8b:4c:5d 0
    11. 3 0 5e:d8:35:40:0e:a5 0
    12. 3 0 ca:d4:37:41:f5:c5 0
    13. $ ovs-appctl fdb/show br3
    14. port VLAN MAC Age
    15. ...
    16. 2 0 5e:d8:35:40:0e:a5 0
    17. 2 0 1a:0d:61:8b:4c:5d 0
    18. 3 0 ca:d4:37:41:f5:c5 0

开启 ovs stp

  1. 开启 stp

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

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

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

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

    1. $ ip netns exec ns2 ping -c 2 1.1.1.3
    2. PING 1.1.1.3 (1.1.1.3) 56(84) bytes of data.
    3. 64 bytes from 1.1.1.3: icmp_seq=1 ttl=64 time=1.48 ms
    4. 64 bytes from 1.1.1.3: icmp_seq=2 ttl=64 time=0.160 ms
    5. ...
    1. $ tcpdump -i br1-br3
    2. ...
    3. 21:24:44.806469 IP 1.1.1.2 > 1.1.1.3: ICMP echo request, id 20724, seq 1, length 64
    4. 21:24:44.806531 IP 1.1.1.3 > 1.1.1.2: ICMP echo reply, id 20724, seq 1, length 64
    5. 21:24:45.807056 IP 1.1.1.2 > 1.1.1.3: ICMP echo request, id 20724, seq 2, length 64
    6. 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. ip link del br1-br2 type veth peer name br2-br1
  2. ip link del br1-br3 type veth peer name br3-br1
  3. ip link del br2-br3 type veth peer name br3-br2
  4. ovs-vsctl del-br br1
  5. ovs-vsctl del-br br2
  6. ovs-vsctl del-br br3
  7. ip netns del ns1
  8. ip netns del ns2
  9. ip netns del ns3

stp 相关命令

    1. # 开启 br1 stp
    2. ovs-vsctl set bridge br1 tp_enable=ture
    3. # 关闭 br1 stp
    4. ovs-vsctl set bridge br1 stp_enable=false
    5. # 设置 br1 stp cost
    6. ovs-vsctl set port br2-br1 other_config:stp-path-cost=100
    7. # 查询 br1 stp 状态
    8. ovs-vsctl get bridge br1 stp_enable
    9. # 设置 br1 的 stp 优先级
    10. ovs-vsctl set bridge br1 other_config:stp-priority=0x7800
    11. # 移除 br1 stp 设置
    12. ovs-vsctl clear bridge br1 other_config
原文地址:https://www.cnblogs.com/dream397/p/12937215.html