zoukankan      html  css  js  c++  java
  • Linux STP介绍

    1. 介绍

    STP(Spanning Tree Protocol)即生成树协议,标准为IEEE802.1D-1998
    STP是一种二层冗余技术,利用STA算法构建一个逻辑上没有环路的树形网络拓扑结构,并且可以通过一定的方法实现路径冗余

    STP

    2. 概念

    2.1 角色

    生成数有如下角色

     - 根桥(Root Bridge) RB, 桥ID最小的桥
    - 根端口(Root Port) RP, 该端口到达根桥的路径是该端口所在网桥到达根桥的最佳路径
    - 指定端口(Designated Port)DP, 每一个网段选择到根桥最近的网桥作为指定网桥, 该网桥到这一网段的端口为指定端口
    - 可选端口(Alternated Port)AP, 即阻塞端口, 既不是指定端口, 也不是根端口的端口

    2.2 端口状态

    STP端口状态有如下几种

     - 断开(Disable):     不收发任何报文
    - 阻塞(Blocking): 不接收或转发数据, 接收但不发送BPDU, 不进行地址学习
    - 监听(Listening): 不接收或转发数据, 接收并发送BPDU, 不进行地址学习
    - 学习(Learning): 不接收或转发数据, 接收并发送BPDU, 开始地址学习
    - 转发(Forwarding): 接收并转发数据, 接收并发送BPDU, 进行地址学习

    一个网桥开启STP后,端口会经历如下过程:

    Blocking(20s) –> Listening(15s) –> Learning(15s) –> Forwarding

    这样大约50秒的时间非根端口转变成为根端口或指定端口PortStates

    2.3 相关参数

    2.3.1 网桥参数

    Bridge Identifier:        标识本网桥, 由网桥的优先级(2 bytes)和网桥的MAC(6 bytes)组成
    Root Path Cost:           从非根桥到根桥的路径开销的总和
    Root Port:                根端口, RP
    Max Age:                  在协议的配置信息被丢弃之前收到的配置信息保留的时间(默认20s)
    Hello Time:               对一个想变成桥或者是根桥的桥在固定的时间发送的配置BPDU信息(默认2s)
    Forward Delay:            从Listening到Learning和从Learning到Forwarding花费的时间(默认15s)
    Bridge Max Age:           桥作为根或想成为根桥的桥标识的它作为根桥的最大年龄
    Bridge Hello Time:        非根桥向根桥发送TCN BPDU的时间间隔
    Bridge Forward Delay:     和上面介绍的Forward Delay值一样
    Topology Change Detected: 用来标识网络拓扑结构改变的布尔变量
    Topology Change:          参数设置表示拓扑改变
    Topology Change Time:     根桥产生配置消息指明拓扑改变的时间间隔
    Hold Time:                在这个时间间隔至少应该收到一个配置BPDU信息

    2.3.2 网桥时间参数

    Hello Timer:                        根桥定时传输配置BPDU信息的时间间隔
    Topology Change Notification Timer: 如果没收到拓扑改变回应消息便会定时发送拓扑改变通知
    Topology Change Time:               定时发送拓扑改变通知来通知桥进行重配

    2.3.3 端口参数

    Port Identifier:             桥的端口ID, 由优先级和端口号组成
    Port State:                  端口状态
    Path Cost:                   本端口的路径开销(see tips below)
    Designated Root:             根桥的桥ID
    Designated Cost:             从这个端口到根桥的路径开销
    Designated Bridge:           指定桥的桥ID
    Designated Port:             指定桥中和它交互的端口ID
    Topology Change Acknowledge: 设置来回应拓扑改变通知
    Configuration Pending:       设置表示在Holdtimer超时后应该传输配置BPDU信息
    Change Detection Enabled:    表示是否理会拓扑改变通知

    2.3.4 端口时间参数

    Message Age Timer:   表示超时丢弃协议信息的时间
    Forward Delay Timer: 和端口状态改变的时间值有关
    Hold Timer:          在这个时间间隔至少应该收到一个配置BPDU信息

    tips: 关于路径开销,可参考<IEEE802.1t路径开销列表>
    通常根据端口的带宽不同,Path Cost值也不同:
    • 10 Mb/s: 100
    • 100 Mb/s: 19
    • 1000 Mb/s: 4
    • 10000 Mb/s: 2

    2.4 BPDU

    2.4.1 介绍

    STP的数据单元称为BPDU(Bridge Protocol Data Unit)
    BPDU是网桥间信息交流的报文,目标MAC地址为:01-80-C2-00-00-00

    网桥之间定期发送BPDU包,交换STP配置信息,以便能够对网络的拓扑、花费或优先级的变化做出及时的响应

    BPDU报文在直连的两个网桥或多个网桥内交换,不能被转发
    没有运行STP协议的网桥将把BPDU报文当作普通业务报文转发

    BPDU被封装在LLC的Payload中

    下面是一个C BPDU

    stp_packet 

    2.4.2 类型

    BPDU有三种类型

     - Configuration BPDU: 即C BPDU, 包含配置信息的BPDU包
    - Topology Change Notification BPDU: 即TCN BPDU, 当检测到网络拓扑结构变化时发送拓扑变化通知BPDU
    - Topology Change Notification Acknowledgment: 即TCA BPDU(TCA flag置1的C BPDU)

    BPDU报文格式如下

    bpdu_field

    2.4.3 发送与接收

    C BPDU:

    只有RB发送C BPDU,它有一个Hello Timer,当这个定时器expire的时候产生一个BPDU的包
    而其他的non-RB在他们的RP中收到这些包之后进行中继,中继的过程中对BPDU中的各项值根据自身的情况进行更新

    TCN BPDU:
    当某个non-RB检测到拓扑变化后,该br会通过RP向RB方向发送TCN BPDU,其他br从它的DP接收到TCN BPDU时,首先从该DP上回应一个TCA BPDU,然后将该TCN BPDU从RP向RB方向发送, 这样TCN BPDU最后会到达RB

    RB则会发出一个C BPDU(topology change置1),表示发现拓扑变化,这个包会被所有br转发,传遍全网,这样所有br都得知拓扑变化,然后做出相应的动作(修改ageing timer: 5m->15s)

    该过程如下图所示:

    tcn_bpdu

    TIP: C BPDU是从RB往树的各个方向传送;TCN BPDU则是从树的某个br上行直至RB

    2.5 选举

    2.5.1 根桥的选举

    网桥初始化以后,都认为自己是Root Bridge,在它认为的指定端口上,周期性的发送C BPDU直到收到BridgeID更小的网桥信息,才直到自己不是根网桥

    或者由于配置管理(端口使能,设置网桥优先级等),端口状态改变,也会引起Root Bridge的重新选举

    2.5.2 根端口的选择

    非根桥的其他网桥将各自选择一条到Root Bridge代价最小的路径,相应端口的角色就成为根端口

    2.5.3 指定端口的选择

    根端口选择以后,选择到根桥路径开销最小的端口作为指定端口

    2.5.4 可选端口的选择

    端口enable,参与选举的拓扑计算,既不是根端口,也不是指定端口,那就是可选端口了

    2.5.5 选择过程

    选举过程如下所示

    选举根桥 -> 根端口 -> 指定端口 -> 其余为阻塞端口

    生成树经过一段时间(默认值是30秒左右)稳定之后,所有端口要么进入转发状态,要么进入阻塞状态
    STP BPDU仍然会定时从各个网桥的指定端口发出,以维护链路的状态
    如果网络拓扑发生变化,生成树就会重新计算,端口状态也会随之改变

    stp_selection

    TIP:
    网桥接受BPDU时开销值增加,发送BPDU时开销值不变
    只有根桥是没有根端口的,根桥的所有端口都是指定端口
    选举根端口,比较接收的BPDU;
    选举指定端口,比较发送的BPDU.

    3. 实现

    3.1 数据结构

    net_bridge:  网桥STP相关参数

    struct net_bridge
    {
        ...
        /* STP */
        bridge_id        designated_root;  /* RB ID */
        bridge_id        bridge_id;        /* ID */
        u32              root_path_cost;   /* 路径开销 */
        unsigned long    max_age;          /* 配置信息保留时间 */
        unsigned long    hello_time;
        unsigned long    forward_delay;
        unsigned long    bridge_max_age;
        unsigned long    ageing_time;
        unsigned long    bridge_hello_time;
        unsigned long    bridge_forward_delay;
    
        u8               group_addr[ETH_ALEN];
        u16              root_port;        /* 本网桥的根端口 */
    
        enum {
            BR_NO_STP,      /* no spanning tree */
            BR_KERNEL_STP,  /* old STP in kernel */
            BR_USER_STP,    /* new RSTP in userspace */
        } stp_enabled;
    
        unsigned char     topology_change;
        unsigned char     topology_change_detected;
    
        struct timer_list    hello_timer;
        struct timer_list    tcn_timer;
        struct timer_list    topology_change_timer;
        struct timer_list    gc_timer;
    };

    net_bridge_port:  网桥端口STP相关参数

    struct net_bridge_port
    {
        /* STP */
        u8                priority;
        u8                state;
        u16               port_no;
        unsigned char     topology_change_ack;
        unsigned char     config_pending;
        port_id           port_id;             /* 本端口的端口ID */
        port_id           designated_port;     /* 发送当前BPDU包的端口ID */
        bridge_id         designated_root;     /* 根桥的网桥ID */
        bridge_id         designated_bridge;   /* 发送当前BPDU包的网桥ID */
        u32               path_cost;           /* 本端口的路径开销 */
        u32               designated_cost;     /* 到根桥的路径开销 */
        unsigned long     designated_age;
    
        struct timer_list        forward_delay_timer;
        struct timer_list        hold_timer;
        struct timer_list        message_age_timer;
    };

    br_config_bpdu:  BPDU包

    struct br_config_bpdu {
        unsigned int topology_change:1;
        unsigned int topology_change_ack:1;
        bridge_id    root;
        int          root_path_cost;
        bridge_id    bridge_id;
        port_id      port_id;
        int          message_age;
        int          max_age;
        int          hello_time;
        int          forward_delay;
    };

    可以发现,br_config_bpdu和C BPDU报文格式对照可以发现,缺少 Protocol ID、Version、Message Type和Flags
    因为Message Type基本在使用的时候可以确定,而Flags则可由topology_change和topology_change_ack来确定
    具体可参考函数br_send_config_bpdu()的实现

    3.2 STP模块

    3.2.1 基本使用

    /*
     * 新增网桥
     * br_dev_setup()
     */
    # brctl addbr br0
    
    /*
     * 向网桥新增端口
     * br_add_if() -> new_nbp() -> br_init_port()
     */
    # brctl addif br0 eth0
    
    /* 
     * 启用和禁用STP
     * on  -> br_stp_start() -> br_port_state_selection()
     * off -> br_stp_stop()
     */
    # brctl stp br0 <on|off>

    3.2.2 数据通路

    static const struct stp_proto br_stp_proto = {
        .rcv = br_stp_rcv,
    };
    static int __init br_init(void)
    {
        stp_proto_register(&br_stp_proto);
        ......
    }

    参考:
    <Linux Bridge STP HOWTO>
    <Spanning Tree Protocol (STP)>
    <Linux的网桥中的STP的实现分析初步>

  • 相关阅读:
    线程池类型场景和问题
    react Antdesign Select添加全选功能
    API与ESB 、ServiceMesh、微服务究竟关系如何?
    RabbitMQ四种Exchange类型
    RabbitMq安装
    kafka 部署
    共享文件夹重启后每次都要输入密码
    algorithm 12 partial_sort_copy
    algorithm 11 nth_element
    algorithm 11 none_of
  • 原文地址:https://www.cnblogs.com/hzl6255/p/3259909.html
Copyright © 2011-2022 走看看