dump file for network 1
dump file for network2
dump file used for improvement of network 1
dump file used for improvement of network 2

UML switches can be created as a switch or a hub. Which do you need to use for sniffing and why?

We need hub here, as switch will not forward Ethernet frames to certain ports according to the filter rule learned during the learning state. Sniffer can only capture the Ethernet frames for other nodes when they are on the same collision domain. In this case, we are taking a look at STP which work on Ethernet level, so hub should be the only choice.

Download the Ubuntu package and install the files in your UML filesystem as per usual.

Please see the work log.

Can you think of reasons not to use the Busybox version of brctl?

The reason is simple, busybox version of brctl miss some functions. The normal brctl provides the following function

vic@umlubuntu:~/uml$ brctl --help
Usage: brctl [commands]
commands:
        addbr           <bridge>                add bridge
        delbr           <bridge>                delete bridge
        addif           <bridge> <device>       add interface to bridge
        delif           <bridge> <device>       delete interface from bridge
        setageing       <bridge> <time>         set ageing time
        setbridgeprio   <bridge> <prio>         set bridge priority
        setfd           <bridge> <time>         set bridge forward delay
        sethello        <bridge> <time>         set hello time
        setmaxage       <bridge> <time>         set max message age
        setpathcost     <bridge> <port> <cost>  set path cost
        setportprio     <bridge> <port> <prio>  set port priority
        show                                    show a list of bridges
        showmacs        <bridge>                show a list of mac addrs
        showstp         <bridge>                show bridge stp info
        stp             <bridge> {on|off}       turn stp on/off

Provide and investigate the reasoning behind each of the following items. Also explain any choices you made in the process.

  1. To be able to analyze the collected data, we need to be able to put it into a timeline.
  2. We need to see all the relevant packets produced by the Spanning Tree Protocol. That means that irrelevant packets can be left out, though your

should carefully decide what they are.

  1. We need to be able to see the content of the STP packets. tcpdump can show that in a nice format so be sure to look into that.
  2. We need to be able to see what (sub)network the packet was retrieved from.

The order in which the nodes send/receive the packet is very important. They have influence on the procedure and the convergence time of the network. The t family of tcpdump can help us

       -t     Don't print a timestamp on each dump line.
 
       -tt    Print an unformatted timestamp on each dump line.
 
       -ttt   Print a delta (micro-second resolution) between current and pre‐
              vious line on each dump line.
 
       -tttt  Print  a  timestamp  in default format proceeded by date on each
              dump line.
 
       -ttttt Print a delta  (micro-second  resolution)  between  current  and
              first line on each dump line.

We can use filters to ensure that only the relevant packets are captured, like protocol = stp, and so on. However, I did not apply any filter in the tcpdump. There are two reasons for that

  1. simplify the scripts: I do not have to let tcpdump use different filter in every different assignment where different packets have to be captured.
  2. I have more complete capture file, every packet is captured, to play with later with either tcpdump itself or wireshark (GUI tool).

There are parameters we can define in tcpdump to let it present us with some more human-friendly packet contents. Like -v -vv -x -xx. The v family, present more verbose output includes more fields and the x family gives out also the packet content instead of only the header.

       -v     When  parsing and printing, produce (slightly more) verbose out‐
              put.  For example,  the  time  to  live,  identification,  total
              length  and  options  in an IP packet are printed.  Also enables
              additional packet integrity checks such as verifying the IP  and
              ICMP header checksum.
 
              When writing to a file with the -w option, report, every 10 sec‐
              onds, the number of packets captured.
 
       -vv    Even more verbose output.  For example,  additional  fields  are
              printed  from  NFS  reply  packets,  and  SMB  packets are fully
              decoded.
 
       -x     When parsing and printing, in addition to printing  the  headers
              of  each  packet,  print the data of each packet (minus its link
              level header) in hex.  The  smaller  of  the  entire  packet  or
              snaplen  bytes  will  be  printed.  Note that this is the entire
              link-layer packet, so for link layers that pad (e.g.  Ethernet),
              the  padding  bytes  will  also be printed when the higher layer
              packet is shorter than the required padding.
 
       -xx    When parsing and printing, in addition to printing  the  headers
              of  each  packet,  print  the data of each packet, including its
              link level header, in hex.

I “mark” the packets with bridges' IDs and their ports IDs. Like, for example

bridge 1:
AA:BB:CC:DD:01:AA - port 1 AA:BB:CC:DD:01:01
                  - port 2 AA:BB:CC:DD:01:02
bridge 2:
AA:BB:CC:DD:02:AA - port 1 AA:BB:CC:DD:02:01
                  - port 2 AA:BB:CC:DD:02:02
                  - port 3 AA:BB:CC:DD:02:03

In this way, I can easily see in the dump file where the specific packet come from. The host and rcS scripts have to be adapted to the change as well.

+ change in host file. It will accept manual MAC addresses assignment. 
  + <code bash>
    bridge)
      macbr=$4
      macif1=$5
      sw1=$6
      #hostname=$macbr
      if [ -z "$7" ];
      then
        #echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname role=$role hostname=$hostname eth0=daemon,,unix,$home/switch/$sw1.ctl macbr=$macbr macif1=$macif1 sw1=$sw1" 
        screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl macbr=$macbr macif1=$macif1 sw1=$sw1
      else
        macif2=$7
        sw2=$8
        if [ -z "$9" ];
        then
          #echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$home/switch/$sw1 eth1=daemon,,unix,$home/switch/$sw2 macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2"
          screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl eth1=daemon,,unix,$switchhome/$sw2.ctl macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2
        else
          macif3=$9
          sw3=$10
          #echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl eth1=daemon,,unix,$switchhome/$sw2.ctl eth2=daemon,,unix,$switchhome/$sw3.ctl macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2 macif3=$macif3 sw3=$sw3"
          screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl eth1=daemon,,unix,$switchhome/$sw2.ctl eth2=daemon,,unix,$switchhome/$sw3.ctl macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2 macif3=$macif3 sw3=$sw3
        fi
      fi
      echo "bridge $hostname started"
      ;;

</code>

+ change in rcS on UML instances. It will change the MAC address of each interface of each bridge accordingly (AA:BB:CC:DD:<Bridge ID>:<port ID>). And assign MAC address (AA:BB:CC:DD:<Bridge ID>:AA) to bridge. 
  + <code bash>

bridge)

      echo "bridge: $hostname"
      mount -t hostfs none /lib/modules/ -o /usr/lib/uml/modules
      modprobe llc
      modprobe stp
      modprobe bridge
      #add br and interfaces
      /bin/brctl addbr $hostname
      ifconfig $hostname hw ether $macbr
      if [ ! -z $macif1 ];
      then
        ifconfig eth0 hw ether $macif1 up
        /bin/brctl addif $hostname eth0
      fi
      if [ ! -z $macif2 ];
      then
        ifconfig eth1 hw ether $macif2 up
        /bin/brctl addif $hostname eth1
      fi
      if [ ! -z $macif3 ];
      then
        ifconfig eth2 hw ether $macif3 up
        /bin/brctl addif $hostname eth2
      fi
      /bin/brctl stp $hostname on
      ifconfig $hostname up
      echo "INFO: bridge $hostname activated"
      ;;

</code>

Witnessing the start-up

Describe in detail (i.e. your own words, not verbatim dumps) what packets are sent, when and why.

What parameters are used in the packets and what are the set to (timing parameters in the BPDU packets etcetera. . . )?

Does the witnessed behaviour of the protocol deviate in any way from the official specification?

<hi #808000>Improvement</hi> Yes. The strange issue I saw is that when there is no change on the network, the TC bit will all of sudden be set. and last for about 36 seconds. Please see the following packets.

179	28.210945	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001
18	28.217348	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
180	30.213560	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001
19	30.220059	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
.
.
35	62.213755	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
197	64.209801	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001

This situation happen more than one time, please see the packets below

320	318.064784	aa:bb:cc:dd:02:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001
151	318.071218	aa:bb:cc:dd:02:02	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8002
.
.
162	340.070109	aa:bb:cc:dd:02:02	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8002

The TC bit does not get cleared after packet 162 at 340 second. But my capture file stopped here. This is more likely to be a implementation error in the software.

Below the read out of tcpdump of the captured packets with option xx and vv

21:48:35.148686 STP 802.1d, Config, Flags [none], bridge-id 8000.aa:bb:cc:dd:01:aa.8001, length 35
	message-age 0.00s, max-age 20.00s, hello-time 2.00s, forwarding-delay 15.00s
	root-id 8000.aa:bb:cc:dd:01:aa, root-pathcost 0
	0x0000:  0180 c200 0000 aabb ccdd 0101 0026 4242
	0x0010:  0300 0000 0000 8000 aabb ccdd 01aa 0000
	0x0020:  0000 8000 aabb ccdd 01aa 8001 0000 1400
	0x0030:  0200 0f00

It is possible to do the full analysis by using tcpdump, but it is just so much easier if we use Wireshark a GUI tool with lots of easy to use built in functions, like merge the dump file, make time line and sort according to different fields.

Network 1

The following image shows how the tree look like after the convergence. Bridge1 is elected as the root bridge. And both port 1 of the other two bridges are used as root port, and both port 2 are blocked.

(Picture of the network needed)

The result of my STP caculation:

+ Bridge 1: by running brctl showstp br1
  + <code bash>

/ # brctl showstp br1 br1 bridge id 8000.aabbccdd01aa designated root 8000.aabbccdd01aa root port 0 path cost 0 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 1.23 tcn timer 0.00 topology change timer 0.00 gc timer 15.23 flags

eth0 (1) port id 8001 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 0.00 designated port 8001 forward delay timer 0.00 designated cost 0 hold timer 0.23 flags

eth1 (2) port id 8002 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 0.00 designated port 8002 forward delay timer 0.00 designated cost 0 hold timer 0.23 flags </code>

+ Bridge 2: by running brctl showstp br2
  + <code bash>

/ # brctl showstp br2 br2 bridge id 8000.aabbccdd02aa designated root 8000.aabbccdd01aa root port 1 path cost 100 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 0.00 tcn timer 0.00 topology change timer 0.00 gc timer 9.96 flags

eth0 (1) port id 8001 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 19.84 designated port 8001 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags

eth1 (2) port id 8002 state blocking designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 19.84 designated port 8002 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags

</code>

+ Bridge 3: by running brctl showstp br3
  + <code bash>

/ # brctl showstp br3 br3 bridge id 8000.aabbccdd03aa designated root 8000.aabbccdd01aa root port 1 path cost 100 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 0.00 tcn timer 0.00 topology change timer 0.00 gc timer 12.84 flags

eth0 (1) port id 8001 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 18.77 designated port 8001 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags

eth1 (2) port id 8002 state blocking designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 18.77 designated port 8002 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags </code>

Now we take a closer look into the captured file.

Below are the first 6 packets I got from the capture. Every bridge start by announcing themselves as the root, on all the ports, however with one exception which is the port 2 of bridge 2, as it may has heard of bridge 1 earlier than announcing itself as root, it starts broadcast bridge1 as the root and give cost of 100.

#bridge 3
1	0.000000	aa:bb:cc:dd:03:01	Spanning-tree-(for-bridges)_00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:03:aa  Cost = 0  Port = 0x8001
4	0.010066	aa:bb:cc:dd:03:02	Spanning-tree-(for-bridges)_00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:03:aa  Cost = 0  Port = 0x8002
 
#bridge 1
2	0.000208	aa:bb:cc:dd:01:01	Spanning-tree-(for-bridges)_00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001
5	0.010070	aa:bb:cc:dd:01:02	Spanning-tree-(for-bridges)_00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
 
#bridge 2
3       0.000632        aa:bb:cc:dd:02:01       Spanning-tree-(for-bridges)_00  STP     Conf. Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001
6	0.011331	aa:bb:cc:dd:02:02	Spanning-tree-(for-bridges)_00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8002

The BPDUs are flooded to Spanning-tree-(for-bridges)_00 (01:80:c2:00:00:00), so every STP talking bridge should receive them. In this case, bridge3 boot up quickly and start the STP election first by broadcast itself as the root on both of his port. The port 1 of bridge 1 start in between and broadcast also itself as the root on both of its port.

Bridge2 starts latest among the three. Its port1 is broadcasting itself as the root, but port2 is broadcasting bridge1 as the root bridge, as it may has received the earlier sent BPDU by others (bridge1 and/or bridge3). Since every bridge is using the same priority (32768), which is also broadcast in the BPDU, we do need the tie breaker here. The MAC address is therefor used. That's why finally bridge1 is elected as the root with lowest MAC address (aa:bb:cc:dd:01:aa).

The BPDUs are sent in the interval of 2 seconds through out the whole procedure. However, after the election, only the root bridge will keep sending out BPDUs. Others only listen.

All the ports enter listening mode first, after the root bridge is elected, they will enter learning port. Then after the forwarding delay (15 seconds) they enter the forward mode.

Many parameters are sent in the BPDU packets

  1. source (MAC of originating ports) and destination (01:80:c2:00:00:00 STP bridge) addresses
  2. BPDU flag
    • TCN (topology change)
    • TCA (acknowledge of TCN)
  3. BPDU type (configuration, TCN, TCA)
  4. root id (root brdige id)
  5. bridge id (bridge's own id)
  6. cost (cost to root)
  7. port id (originating port)
  8. bridge priority (32768)
  9. message age (start with 0)
  10. max age (20)
  11. Hello time (2)
  12. forward delay (15)

What happens if the topology changes?
Depending on the role of the down port of bridge, the STP will behave differently. If it is not a port on the root bridge, the bridge will just unblock the formerly blocked port and the network flow will not be disturbed. But in case of a root port or root bridge down, the topology of the whole network will be changed, hence a TCN will be triggered and acknowledged by others.

What happens if you disturb the network by shutting down the root bridge?
<hi #808000>Improvement: Does the witnessed behaviour of the protocol deviate in any way from the official specification?</hi>
I did not notice any abnormal behavior in the log nor on the bridges. The STP on each bridge just behave like described in the book and slides of Karst.

Explore as many possibilities for situations that could/should/may give rise to problems as can be imagined (i.e. more than one), describe them and then test them.

I turn off STP on bridge1 (root). So a new election is needed. However, it will not happen until the max age (20 seconds) is reached. We can see this clearly from the capture below

126	118.339826	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
127	138.334867	aa:bb:cc:dd:03:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:03:aa  Cost = 0  Port = 0x8001
128	138.334869	aa:bb:cc:dd:02:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001
 
129	138.335206	aa:bb:cc:dd:03:01	01:80:c2:00:00:00	STP	Topology Change Notification

<hi #808000>Improvement</hi>
Bridge2 is elected as the new root bridge, as it has lowest bridge ID (MAC address) and port 1 and 2 of it are serving as the DP.

br2 
 bridge id              8000.aabbccdd02aa
 designated root        8000.aabbccdd02aa
 root port                 0                    path cost                  0
 max age                  20.00                 bridge max age            20.00
 hello time                2.00                 bridge hello time          2.00
 forward delay            15.00                 bridge forward delay      15.00
 ageing time             300.00
 hello timer               1.87                 tcn timer                  0.00
 topology change timer     0.00                 gc timer                   7.87
 flags  
 
eth0 (1)
 port id                8001                    state                forwarding
 designated root        8000.aabbccdd02aa       path cost                100
 designated bridge      8000.aabbccdd02aa       message age timer          0.00
 designated port        8001                    forward delay timer        0.00
 designated cost           0                    hold timer                 0.87
 flags  
 
eth1 (2)
 port id                8002                    state                forwarding
 designated root        8000.aabbccdd02aa       path cost                100
 designated bridge      8000.aabbccdd02aa       message age timer          0.00
 designated port        8002                    forward delay timer        0.00
 designated cost           0                    hold timer                 0.87
 flags  

bridge3 port 1 is the root port for bridge3. It has lower port ID (0x8001), so it preferred over port2 (0x8002)

/ # brctl showstp br3
br3
 bridge id              8000.aabbccdd03aa
 designated root        8000.aabbccdd02aa
 root port                 1                    path cost                100
 max age                  20.00                 bridge max age            20.00
 hello time                2.00                 bridge hello time          2.00
 forward delay            15.00                 bridge forward delay      15.00
 ageing time             300.00
 hello timer               0.00                 tcn timer                  0.00
 topology change timer     0.00                 gc timer                   3.86
 flags
 
 
eth0 (1)
 port id                8001                    state                forwarding
 designated root        8000.aabbccdd02aa       path cost                100
 designated bridge      8000.aabbccdd02aa       message age timer         19.71
 designated port        8001                    forward delay timer        0.00
 designated cost           0                    hold timer                 0.00
 flags
 
eth1 (2)
 port id                8002                    state                  blocking
 designated root        8000.aabbccdd02aa       path cost                100
 designated bridge      8000.aabbccdd02aa       message age timer         19.71
 designated port        8002                    forward delay timer        0.00
 designated cost           0                    hold timer                 0.00
 flags

BPDU number 126 (time 118), we still have bridge 1 as the root and the root is then brought down by me. BPDU number 127 (time 138, which is 20 seconds later), bridge 3 reached max age and start sending out BPDU to announce that there is a topological change and itself should be the new root. In BPDU 128 (time 138), bridge 2 does the same. A new election hence should be started. Probably, in this round bridge2 will become the new root, due to the lower bridge id. At almost the same time, bridge 3 send out the TCN to yield that there is a change on topology.

As shown below,

129	138.335206	aa:bb:cc:dd:03:01	01:80:c2:00:00:00	STP	Topology Change Notification
136	138.346604	aa:bb:cc:dd:03:01	01:80:c2:00:00:00	STP	Topology Change Notification
 
137	139.421463	aa:bb:cc:dd:02:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001
138	139.432378	aa:bb:cc:dd:02:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001

The TCN is sent in a very high frequency. Same goes with the TCA. As each of the TCN will be acknowledged by a TCA. The TCA is a normal looking BPDU packet with only the BPDU flag TCA bit set while TCN is a packet in different form. It is a packet without content and only has the BPDU type set to 0x80. Interesting enough, if we do not look at the content and TC flag of TCA, we will have the flag of TCA also as 0x80.

Now bridge2 takes over the role as root bridge. And broadcast in every 2 seconds the BPDU.

investigate more cases

  • Turn back on the bridge 1

In the same network, I turn on the previously turned off bridge1. It starts broadcasting BPDU to announce itself as the root. And amazingly enough, in such a huge change of topology. There is no TCN nor TC flag. Both bridge2 and 3 will quietly accept it and use bridge1 as the root again.

184	185.325847	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001
185	185.336085	aa:bb:cc:dd:02:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8002
186	185.336599	aa:bb:cc:dd:03:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8002
187	185.336928	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
188	186.322706	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001
189	186.333423	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002

<hi #808000>Improvement</hi>

126	118.339826	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002

This is the last BPDU from previous root bridge 1 at time 118 second.

172	172.427118	aa:bb:cc:dd:02:01	01:80:c2:00:00:00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001
173	174.414214	aa:bb:cc:dd:02:01	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8001

This 172 packet is the last packet from new root bridge 2 with TC set. After that it broadcasts normal 2 second's BPDU.

184	185.325847	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001

This is the first packet from re-turn on bridge1 at time 185 second.

Next all the bridges just send BPDU to compete for the root role

185	185.336085	aa:bb:cc:dd:02:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8002
186	185.336599	aa:bb:cc:dd:03:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8002
187	185.336928	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
188	186.322706	aa:bb:cc:dd:01:01	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8001
189	186.333423	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002

No TC, no TCN, no TCA. Only the down of the root bridge will be notified via TCN and TC. The join of a “better” root is not notified via these packets. A new election just happen and every other bridges follow quietly.

network 2

Result of STP calculation

+ Bridge 1 (root)
  + <code bash>

/ # brctl showstp br1 br1 bridge id 8000.aabbccdd01aa designated root 8000.aabbccdd01aa root port 0 path cost 0 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 1.72 tcn timer 0.00 topology change timer 4.84 gc timer 1.72 flags TOPOLOGY_CHANGE TOPOLOGY_CHANGE_DETECTED

eth0 (1) port id 8001 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 0.00 designated port 8001 forward delay timer 0.00 designated cost 0 hold timer 0.72 flags

eth1 (2) port id 8002 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 0.00 designated port 8002 forward delay timer 0.00 designated cost 0 hold timer 0.72 flags

eth2 (3) port id 8003 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 0.00 designated port 8003 forward delay timer 0.00 designated cost 0 hold timer 0.72 flags </code>

+ Bridge 2
  + <code bash>

/ # brctl showstp br2 br2 bridge id 8000.aabbccdd02aa designated root 8000.aabbccdd01aa root port 2 path cost 100 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 0.00 tcn timer 0.00 topology change timer 0.00 gc timer 15.04 flags

eth0 (1) port id 8001 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd02aa message age timer 0.00 designated port 8001 forward delay timer 0.00 designated cost 100 hold timer 1.04 flags

eth1 (2) port id 8002 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 19.92 designated port 8002 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags

eth2 (3) port id 8003 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd02aa message age timer 0.00 designated port 8003 forward delay timer 0.00 designated cost 100 hold timer 1.04 flags </code>

+ Bridge 3
  + <code bash>

/ # brctl showstp br3 br3 bridge id 8000.aabbccdd03aa designated root 8000.aabbccdd01aa root port 3 path cost 100 max age 20.00 bridge max age 20.00 hello time 2.00 bridge hello time 2.00 forward delay 15.00 bridge forward delay 15.00 ageing time 300.00 hello timer 0.00 tcn timer 0.00 topology change timer 0.00 gc timer 6.92 flags

eth0 (1) port id 8001 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd03aa message age timer 0.00 designated port 8001 forward delay timer 0.00 designated cost 100 hold timer 0.92 flags

eth1 (2) port id 8002 state blocking designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd02aa message age timer 19.92 designated port 8003 forward delay timer 0.00 designated cost 100 hold timer 0.00 flags

eth2 (3) port id 8003 state forwarding designated root 8000.aabbccdd01aa path cost 100 designated bridge 8000.aabbccdd01aa message age timer 19.93 designated port 8003 forward delay timer 0.00 designated cost 0 hold timer 0.00 flags </code>

This is a more complicated setting than network 1, in the sense that not only bridge 1 (root) is sending period BPDU but also bridge 2 is sending BPDU on port 3 (connected to bridge3) with weight 100, to tell bridge 3 that it has a route to root bridge with cost 100.

1	0.000000	aa:bb:cc:dd:03:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:03:aa  Cost = 0  Port = 0x8002
2	0.000455	aa:bb:cc:dd:02:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:02:aa  Cost = 0  Port = 0x8003
3	0.074078	aa:bb:cc:dd:03:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:03:aa  Cost = 0  Port = 0x8003
4	0.074313	aa:bb:cc:dd:01:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8003
5	0.140022	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
6	0.991514	aa:bb:cc:dd:03:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8002
7	1.066574	aa:bb:cc:dd:01:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8003
8	1.113405	aa:bb:cc:dd:02:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8003
9	2.033120	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
10	2.068905	aa:bb:cc:dd:01:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8003
11	2.116324	aa:bb:cc:dd:02:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8003
12	3.993914	aa:bb:cc:dd:02:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8003
 
13	4.031611	aa:bb:cc:dd:01:02	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
14	4.068319	aa:bb:cc:dd:01:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8003
15	5.998564	aa:bb:cc:dd:02:03	01:80:c2:00:00:00	STP	Conf. Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8003

Only the first 12 BPDUs are related to the root election. The later three (13 to 15) are period BPDUs. Two sent by root bridge with cost 0, and one sent by port 3 of bridge 2, which is connected to the blocking port of bridge 3. This shows that even if the port is in the state of blocking it is still taking part in the STP and listening to BPDUs.

If I turn off the port 3 on bridge 3 which is the root port for it, port 2 will immediately be put into listening state. And send out BPDU to announce itself as root. Only after the first receipt of the root BPDU, it will use the lower root id bridge as the root. Port two will then be put into learning mode, after 15 seconds' forward delay, it will be in forwarding state.

If I shutdown the root bridge in this setting, it does not make too much sense, as there is no fault tolerance in the network. If any one of the bridge, it will break the current network setting and leave us with a totally different two bridge network. The reachability of the hosts is gone. However, let's suppose the root bridge 1 is down. Then host1 will be disconnected from the rest of the network, and bridge 2 will be the new root.

Analyse both networks using the above approach.

<hi #808000>You can turn off individual ports on the bridges. In that case there is fault tolerance! Network 2 needs more work (more tests)</hi>
I will first turn off one of the ports on root bridge, in this case bridge1 port 2. As there is no more direct link to root from bridge 2, bridge2's port to port 1 on root should be blocked, however, since the connected root port is down, it will not receive BPDU, so it will not be put into block mode, rather it will stay in the forwarding mode broadcast BPDU to the UML hub. Its port to bridge3 should be left untouched in forwarding state. Port on bridge3 to bridge2 become DP, the other one should become RP. Let's see if it works as expected.

port 2 on root brdige1 is down, below is the message on bridge2

br2: neighbor 8000.aa:bb:cc:dd:01:aa lost on port 2(eth1)
br2: topology change detected, propagating

Next, the previously blocked port of bridge3 will be bring up. And there is TCN generated to announce the change of topology as we can see from the message below.

br3: port 3(eth2) entering learning state
br3: topology change detected, sending tcn bpdu

So everything works as expected. In a triangle topology even one port is down does not take down the whole network. We can conclude certain level of fault tolerance. But not as high as in network 1.

Next, I bring back the disabled port on root, wait till the network re-convergence. Then try to disable a port on bridge3's RP. Just to see how smooth the switch of port state can be. And how fast it can be.

turn down the interface on bridge3 to root bridge 1

/ # ifconfig eth2 down
br3: port 3(eth2) entering disabled state
br3: port 2(eth1) entering listening state

immediately, the previously blocked port 2 enter listening state. Same time, the TCNs are sent from two bridges

182	115.006268	aa:bb:cc:dd:02:02	Spanning-tree-(for-bridges)_00	STP	Topology Change Notification
183	115.040180	aa:bb:cc:dd:03:02	Spanning-tree-(for-bridges)_00	STP	Topology Change Notification

bridge3 is the the place where the change occurs, but maybe it is too busy with the change, bridge2 is just a tiny bit faster in sending out the TCN.

186	116.415578	aa:bb:cc:dd:01:03	Spanning-tree-(for-bridges)_00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8003
187	116.589078	aa:bb:cc:dd:01:02	Spanning-tree-(for-bridges)_00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
188	116.653639	aa:bb:cc:dd:02:03	Spanning-tree-(for-bridges)_00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8003

The the patent of the repetation of the BPDUs goes back to normal. bridge1 is still the root, so both of its ports are sending out BPDUs. And bridge2 port 3 became DP for bridge3, and sending out BPDU. Its port 2 is the RP. bridge3's port 2 is disabled. And port3 is used as RP.
The switch is real fast and smooth, from the above packets we can calcute that the total process of switching takes only around 1.5 seconds. It is the full convergence time, if we look at the packets below, the time of convergence should be reduced to half a second

184	115.588295	aa:bb:cc:dd:01:02	Spanning-tree-(for-bridges)_00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 0  Port = 0x8002
BPDU flags: 0x81 (Topology Change Acknowledgment, Topology Change)
 
185	115.652761	aa:bb:cc:dd:02:03	Spanning-tree-(for-bridges)_00	STP	Conf. TC + Root = 32768/0/aa:bb:cc:dd:01:aa  Cost = 100  Port = 0x8003
BPDU flags: 0x81 (Topology Change Acknowledgment, Topology Change)

Make a thorough comparison between the analyses of both networks.

Are the observations the same for both networks? What, if any, are the differences?

network 1 is smaller in size but complicated topology wise due to the loops created by the connections to the switches. It probably takes more CPU cycles from the bridge to run STP algorithm.

<hi #808000>Improvement: why netowrk 1 take more CPU cycles on STP</hi>
There are 3 portential loops in first network: bridge 1 and 2, bridge 1 and 3, bridge 2 and 3. There are even more combinations with up/down ports to form more complicated issues. However, in network2, there is max one physical loop as it is a triangle. STP is the protocol created with loop emission as goal, it will have to work harder within a heavy loop environment.

But network 1 comes with more fault tolerance than network 2. there are three redundant links between hosts. Any two bridges can be down, and at most 4 connections can be down, as long as the broken links comes in pairs. In network 2, with only one bridge down the host connected to it will be inaccessible.

STP is not sticky and deterministic. If the election criteria keeps the same, like bridge id, port id and etc, the root bridge will always be the same one. Even after it went down for a while, after it came back online, it will take over the root role smoothly.