> ## Content Index
> Fetch the complete content index at: https://www.pinglabz.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# UDLD: Detecting Unidirectional Links Before They Loop
- URL: https://www.pinglabz.com/udld-unidirectional-link-detection/
- Published: 2026-07-12T08:25:26.000Z
- Updated: 2026-08-24T05:22:33.000Z
- Description: A link that transmits but cannot receive never hears the BPDU telling it to block, and spanning tree loops. UDLD detects unidirectional links and shuts the port first. Covers normal and aggressive mode with real CML output.
- Author: Jaime
- Tags: STP, Labs, CCIE, #Import 2026-08-01 19:54

Spanning tree has one blind spot, and it is a dangerous one. STP decides whether to block a port based on the BPDUs it receives. But what if a link can send in one direction and not the other? A switch that can transmit but not receive will never hear a BPDU telling it to block - so it keeps a redundant port forwarding, and you get a loop that spanning tree was specifically designed to prevent, on the exact link that was supposed to be protected.

UDLD is the fix. It detects a link that has gone unidirectional and shuts the port before the loop forms. This article covers how it works, aggressive mode, and real output from a CML lab - plus an honest note about what a virtual lab can and cannot reproduce. For the fundamentals, start at the [complete spanning tree guide](https://www.pinglabz.com/spanning-tree-protocol/).

## How a link goes unidirectional

It sounds exotic. It is not. The usual causes are mundane and physical:

- **A fiber pair with one strand broken or dirty.** Light goes one way, not the other. Both ends see "link up" because each is receiving light on its RX - but the data path is one-way.
- **A miswired patch.** TX on one end is cross-connected to something that is not the far end's RX.
- **A media converter or SFP failing on one channel.**
- **A GBIC seated just badly enough that one direction works.**

The insidious part is that **the interface stays up**. `show interfaces` reports the port as connected. The line protocol is up. Everything looks healthy - and a redundant port that should be blocking is forwarding, because the BPDU that would have blocked it never arrived.

## How UDLD works

UDLD sends its own small Layer 2 frames (to a well-known multicast MAC) that carry the sender's device ID and port ID. The protocol works by **echo**:

1. Switch A sends a UDLD frame saying "I am device A, port X".
2. Switch B receives it, and sends back a frame saying "I am device B, port Y, and I can see device A port X".
3. Switch A receives that echo. It now knows: B can see me. The link is bidirectional.

If A stops seeing its own identity echoed back by B, it concludes the far end cannot receive what A is sending - the link is unidirectional - and it acts.

## The two modes

Normal mode

Detects a unidirectional link and marks the port *undetermined*, logging it. It does **not** shut the port. It tells you; it does not act.

Aggressive mode

After losing echo, it tries eight times to re-establish the neighbor, once per second. If it cannot, it **errdisables the port**. It acts.

**Use aggressive mode.** Normal mode detecting a loop and merely logging it is not much use at 3 a.m. when the loop is already melting your CPU. Aggressive mode also catches a subtler case: a link where both directions were working and then one silently stops (a "connection lost" scenario), not just links that were unidirectional from the start.

## Configuration - and the copper gotcha

The global command:

```
udld aggressive
```

Here is the catch that wastes people an afternoon. **The global command only arms fiber ports.** On copper, UDLD does nothing until you enable it per interface. From the lab, after the global command:

```
SW1#show udld Et0/0
Port enable administrative configuration setting: Disabled
Port enable operational state: Disabled
Current bidirectional state: Unknown
```

Disabled, despite the global config. The fix is per-interface:

```
interface Ethernet0/0
 udld port aggressive
```

The reasoning is historical: UDLD was designed for fiber, where unidirectional failures are common. Copper's auto-negotiation already detects most one-way faults electrically, so Cisco does not auto-arm UDLD on copper. But copper faults still happen, so if you want UDLD on a copper link you ask for it explicitly.

## Verification: a healthy link

```
SW1#show udld Et0/0
Port enable administrative configuration setting: Enabled / in aggressive mode
Port enable operational state: Enabled / in aggressive mode
Current bidirectional state: Bidirectional
Current operational state: Advertisement - Single neighbor detected
Message interval: 7000 ms
Time out interval: 5000 ms
    Entry 1
    Current neighbor state: Bidirectional
    Device ID: 2039889
    Port ID: Et0/0
    Neighbor echo 1 device: 2039885
    Neighbor echo 1 port: Et0/0
    TLV CDP Device name: SW2
```

Everything you want to see is here:

- `Current bidirectional state: Bidirectional` \- the link is confirmed two-way.
- `Neighbor echo 1 device / port` \- SW1 can see its own identity being echoed back. That is the whole detection mechanism, made visible.
- `TLV CDP Device name: SW2` \- the neighbor identified itself.
- `Message interval: 7000 ms` \- UDLD sends a message every 7 seconds by default in the advertisement phase.

## What a virtual lab cannot do, and how we handle it honestly

Here is where PingLabz is going to be straight with you rather than fake a screenshot. A CML lab connects nodes with virtual links that are inherently bidirectional. There is no way to break one strand of a fiber that does not physically exist. **We cannot faithfully reproduce a genuine unidirectional-link failure in the lab, so we are not going to show you invented errdisable output and pretend it is real.**

What we *can* show, and did above, is UDLD in aggressive mode, fully operational, in a confirmed bidirectional state, with the echo mechanism visible. What you would see when it fires on real hardware is this:

```
%UDLD-4-UDLD_PORT_DISABLED: UDLD disabled interface Gi1/0/1, unidirectional link detected
%PM-4-ERR_DISABLE: udld error detected on Gi1/0/1, putting Gi1/0/1 in err-disable state
```

And `show udld` would report `Current bidirectional state: Unknown` with the port in errdisable.

An expert reader can tell the difference between a lab that models a fault honestly and one that stages fake output. We would rather show you the healthy state and the real recovery config than pretend.

## Recovery: pair it with errdisable recovery

When aggressive UDLD errdisables a port, it stays down until you clear it. In a lot of unidirectional failures - a dirty connector, a marginal SFP - the fault is transient or self-clears when someone reseats the optic. Rather than dispatching an engineer for a port that may already be fine, configure automatic recovery:

```
errdisable recovery cause udld
errdisable recovery interval 300
```

From the lab, UDLD is armed as a recovery cause:

```
SW1#show errdisable recovery
ErrDisable Reason            Timer Status
bpduguard                    Enabled
udld                         Enabled
...
Timer interval: 60 seconds
```

Now the port re-tries every 300 seconds. If the link is genuinely bidirectional again, it comes back on its own. If not, it errdisables again - which is exactly the behavior you want. The full recovery mechanism is covered in [switch administration](https://www.pinglabz.com/switch-administration-sdm-errdisable/).

Set the recovery interval long enough (300 seconds is sensible) that a genuinely broken link is not flapping in and out of service every minute - that would be worse than leaving it down.

## UDLD vs the alternatives

UDLD

**Detects:** unidirectional links, at Layer 2  
**Speed:** seconds (echo-based)  
**Scope:** the specific fault STP is blind to

Loop guard

**Detects:** a blocking port that stops receiving BPDUs  
**Action:** keeps it blocking (loop-inconsistent) rather than letting it go forwarding  
**Complements UDLD** \- belt and braces

BFD

**Detects:** loss of a bidirectional forwarding path (Layer 3)  
**Speed:** sub-second  
**Different job** \- for routing convergence, not L2 loop prevention

**Run UDLD and loop guard together.** They overlap deliberately. UDLD detects the physical unidirectional condition; loop guard handles the case where a blocking port stops hearing BPDUs for any reason. Neither is a complete substitute for the other, and the belt-and-braces combination is standard on any well-run switched core.

## Key takeaways

- A unidirectional link keeps the interface "up" while data flows only one way. STP cannot see it, so a port that should block keeps forwarding, and you get a loop.
- UDLD detects this with echo frames: if a switch stops seeing its own identity echoed back, the link is one-way.
- **Use aggressive mode.** Normal mode only logs; aggressive mode errdisables the port and also catches links that go one-way after working.
- The global `udld aggressive` command **only arms fiber**. On copper you must add `udld port aggressive` per interface.
- `Current bidirectional state: Bidirectional` plus a visible neighbor echo is a healthy link.
- A virtual lab cannot create a genuine unidirectional fault, so we show the healthy operational state and the real recovery config rather than staging fake errdisable output.
- Pair aggressive UDLD with `errdisable recovery cause udld` and a sensible interval, and run loop guard alongside it.

Next: [storm control](https://www.pinglabz.com/storm-control-configuration/), stopping a broadcast flood at the port. The full cluster index lives on the [spanning tree pillar](https://www.pinglabz.com/spanning-tree-protocol/).