Have you ever wondered why per-VLAN spanning tree only accepts bridge priority values in increments of 4096? I have. I spun up a lab and Wireshark to figure it out.
In Cisco IOS, if you attempt to configure a bridge priority value that is not an increment of 4096 the CLI will print a helpful error containing all allowed values.
SW5(config)#spanning-tree vlan 4094 priority 2
% Bridge Priority must be in increments of 4096.
% Allowed values are:
0 4096 8192 12288 16384 20480 24576 28672
32768 36864 40960 45056 49152 53248 57344 61440
History
*Disclaimer: This is my take on it, I was not born yet when some of this occurred.
Way back when spanning tree was invented, all bridge ports belonged to the same broadcast domain. There was no VLAN construct to logically carve up bridge ports to create different segments. Because of this, only a single spanning tree topology was necessary to prevent bridging loops. Spanning tree was devised with a 16-bit bridge priority value to give administrators the ability to determine which bridge would become the root of the spanning tree. I image that most (maybe all) implementations of the original spanning tree spec would allow any priority value between 0 and 65535, but this was all before my time. Sometime later, someone decided that it would be cool to be able to carve up bridges into multiple virtual LANs to provide segmentation and broadcast isolation. All good in my book. Sometime after that someone realized that it could be advantageous to be able to have different spanning tree topologies per virtual LAN. Fine idea. If we’re going to send a spanning tree message (BPDU) for each VLAN, how can we tell them apart without redesigning the fields? If backwards compatibility isn’t maintained, people might get mad.
The solution that was chosen is to steal some bits from the bridge priority field and repurpose them. Nobody needs 65535 possible bridge priority values anyways. Because there are 4096 VLAN numbers, we need 12 bits to represent them. Recall that the original bridge ID was 16 bits, so if we use the 12 least significant bits, we can use this to represent the VLAN number. This VLAN representation in the BPDU is called the System Extended ID.
This leaves us with the 4 high order bits to represent the Bridge Priority in bit positions 32768, 16384, 8192, and 4096.
VLAN 1 Example
In the snippet above we can see that the Root Bridge Priority is 32768 and the System Extended ID (VLAN number) is 1. When you highlight the Extended ID in Wireshark, it highlights the Bridge Priority and System Extended ID values in Hexadecimal, 80 01. Below is this field broken down into binary with a pipe separating the Bridge Priority and VLAN number.
Author Edit: Sorry for the ugly line wrap on mobile devices.
32768 16384 8192 4096 | 2048 1024 512 256 128 64 32 16 8 4 2 1
1 0 0 0 | 0 0 0 0 0 0 0 0 0 0 0 1
VLAN 4094 Example
For this example, I left the priority at the Cisco default of 32768 but I created and trunked VLAN 4094, the highest value permitted in Cisco IOS. With the System Extended ID highlighted again, we can see that the hex value for the bridge priority and VLAN number is 8F FE.
32768 16384 8192 4096 | 2048 1024 512 256 128 64 32 16 8 4 2 1
1 0 0 0 | 1 1 1 1 1 1 1 1 1 1 1 0
From these examples, we can see that by borrowing the bottom 12 bits to represent the VLAN number, the smallest non 0 value we’re left with for the Bridge Priority is 4096.