First, like the others have mentioned you have no bridging loop here due to running a Portchannel. That said, running STP is still fine. Let me clear some confusions on how these commands work on Cisco switches.
spanning-tree portfast trunk
This command is supposed to be run on trunk ports towards non bridging devices, such as a server with multiple VLANs or a router. This command should not be run on trunks towards switches because the port will bypass the listening and learning phase which could potentially create a bridging loop.
If you have an interface configured like this:
interface x/x
spanning-tree portfast
spanning-tree bpdufilter enable
spanning-tree bpduguard enable
BPDU guard will never kick in because BPDU filter is filtering both the outgoing and incoming BPDUs. This also means that the port can never lose its Portfast status which it would normally do if BPDUs were received inbound. If you remove the filter then BPDU guard will kick in and shutdown the port if a BPDU is received. This is done before the port can lose its Portfast operatational state so basically the port will always operate in Porfast operational mode.
If you apply the commands globally instead:
spanning-tree portfast default
spanning-tree portfast bpdufilter default
spanning-tree portfast bpduguard default
The first command enables Portfast on all access ports.
When BPDU filter is applied globally, the difference is that it sends out 11 BPDUs before going silent. Because normally one BPDU is sent out every 2 seconds and the default MaxAge is 20 seconds that means that if there is a device at the other end that can process BPDUs, at least one BPDU would be received when the old BPDU (if there was one) has expired.
If a BPDU is received inbound when BPDU filter is applied globally then the port stops filtering and it will lose its Portfast status.
The BPDU guard default command will only apply to ports that are in a Portfast operational state.
If you combine these three commands together then what will happen is that when a BPDU is received the port loses its BPDU filter, BPDU guard can then kick in. The port will never lose its Portfast operational state because the port is shutdown before.
So you see when applied to the interface BPDU guard can never kick in but if you apply it globally it can.
If you run just Portfast globally and BPDU filter globally then if a BPDU comes in, the port loses the filter and loses the Portfast operational state and will operate as a normal port.
The ifCounterDiscontinuityTime is triggered when interfaces are dynamically removed from a device and then that same interface is dynamically re-added. I tested this using a loopback interface but I believe the behavior would be the same for modular interface whose existence would change based on whether or not the module was present. The steps to reproduce this are below and there is some further reading on this topic in the RFC here: https://www.rfc-editor.org/rfc/rfc2863#section-3.1.5
1. Create loopback 100 and find it's ifindex
router1#conf t
router1(config)#int loopback100
router1(config-if)#end
[user@host logs]$ snmpwalk -v 2c -c $COMMUNITY router1 .1.3.6.1.2.1.2.2.1.2 | grep Loopback
IF-MIB::ifDescr.67 = STRING: Loopback100
2. Check the current value of ifCounterDiscontinuityTime for Loopback100
[user@host logs]$ snmpwalk -v 2c -c $COMMUNITY router1 1.3.6.1.2.1.31.1.1.1.19.67
IF-MIB::ifCounterDiscontinuityTime.67 = Timeticks: (0) 0:00:00.00
3. Remove Loopback100 and check the value of ifCounterDiscontinuityTime
router1(config)#no int loopback 100
[user@host logs]$ snmpwalk -v 2c -c $COMMUNITY router1 1.3.6.1.2.1.31.1.1.1.19.67
IF-MIB::ifCounterDiscontinuityTime.67 = No Such Instance currently exists at this OID
4. Re-add Loopback100 and check the value of ifCounterDiscontinuityTime
router1(config)#int loopback 100
[user@host logs]$ snmpwalk -v 2c -c $COMMUNITY router1 1.3.6.1.2.1.31.1.1.1.19.67
IF-MIB::ifCounterDiscontinuityTime.67 = Timeticks: (111308186) 12 days, 21:11:21.86
Best Answer
Having portfast on a inter-switch link is not the best of ideas, indeed.
Switches and Bridges should take the time needed (going through listening/learning phases) to converge to a loop free L2 topology. Rapid-Spanning-Tree, Rapid-PVST (Cisco), and MST are there to speed that process up from the classic 30sec of Spanning-Tree down to like 2-5 seconds.
On the other hand, not having portfast on a (non-bridging) end device's port is practically never a good idea - no matter if that port is "access" or "trunk".
Routers (not necessarily restricted the "on a stick" scenario) often run 802.1q tagged (sub)interfaces, and hypervisors such as VMware have trunk ports too.
And these devices are (more often than not) very unhappy with the 30seconds of black-hole situation after they see the line protocol go "up", just as a DCHP client on an access port is not happy with having to retry after more than 30 seconds.
VMware ESXi for example, when a link comes up, wants to send out a burst of RARP messages (at least one for each VM, with the VM's MAC address as source) through the link that has just come "up" (a feature called "notify switches" somewhere deep in the vSwitch's configuration). This helps the switches involved to immediately update their MAC address tables for the given VLANs. ESXi does this within a fraction of a second after it detects the "line protocol up" event.
A non-portfast trunk port going through LIS/LRN phases of STP (or the LRN of Rapid-PVST) will just break the "notify switches" feature. Users and admins will be quite unhappy, because their VMs might remain unreachable for even longer than these 30seconds, until the VM sees fit to send its first frame and the switches re-learn the VM's MAC address.
Even Cisco's DTP (Dynamic Trunking Protocol) interferes with "notify switches", as it keeps the port blocking for something less than 1 second before aborting negotiation.
switchport nonegotiate
becomes your friend in these situations.Pretty much the same thing can be said for routers and their dynamic routing protocols. As soon as they detect "line protocol up", they want to launch their hello and discovery mechanisms. Blackholeing them with non-portfast ports for 30seconds is just extending network reconvergence time, ruining the router admin's own efforts to optimize to sub-10-seconds reconvergence. They'll be standing at your desk, tapping their feet.
Be sure to know the difference between
spanning-tree portfast
andspanning-tree portfast trunk
for classic IOS switches, respectivelyspanning-tree port type edge
andspanning-tree port type edge trunk
for more recent IOS and NX-OS (syntax may vary in details, check your documentation), and apply them correctly.Without the
trunk
keyword, the portfast setting is only active if the port is in 'access' mode. If you configureswitchport mode trunk
for an edge device, you have to include thetrunk
keyword in the portfast command, too.Yes, a portfast enabled port skips the LIS/LRN phases of spanning-tree.
That's why you should always add bpduguard to portfast ports. Some Cisco switching platforms support the
spanning-tree portfast bpduguard default
global command, so you get bpduguard implicitely on every portfast enabled port, and you cannot forget it.Yes, I've been running switched networks in quite a range of sizes with
portfast trunk
andbpduguard
for the end devices for years.And now for the question about the warning: The warning about (temporary) loops - to some degree - might be a leftover from the days when trunks were primarily a thing for inter switch links, bpduguard was not widely deployed and DTP was still a thing. If one connected a switch to another switch without setting the port modes explicitely, DTP might've negotiated an inter-switch trunk, and these should never be "portfast". Hence Cisco probably decided to let
spanning-tree portfast
be without effect for trunk ports. But that's more speculation than actual knowlegde.Suggested reading: Any of the many Cisco documents titled "Configuring Optional Spanning-Tree Features", usually part of the collection of Configuration Guides.
Pick one that fits the given platform and software generation. One example: https://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst3750x_3560x/software/release/15-2_4_e/configurationguide/b_1524e_consolidated_3750x_3560x_cg/b_1524e_consolidated_3750x_3560x_cg_chapter_01000001.html