Skip to content
MikroTik RouterOS Docs

MikroTik RouterOS MPLS Traffic Engineering: Explicit Path Control

MikroTik RouterOS MPLS Traffic Engineering: Explicit Path Control

Section titled “MikroTik RouterOS MPLS Traffic Engineering: Explicit Path Control”

RouterOS Version: 6.x / 7.x (syntax differs) Difficulty: Advanced Estimated Time: 60 minutes

MPLS Traffic Engineering (MPLS-TE) gives you explicit control over how traffic traverses your network. Unlike standard IP routing where packets follow the shortest path calculated by your IGP, TE tunnels let you define specific paths based on bandwidth requirements, link properties, or administrative policies.

The key difference from LDP-based MPLS is control: LDP automatically creates label-switched paths following IGP routes, while RSVP-TE creates paths you define - either explicitly hop-by-hop, or dynamically via Constrained Shortest Path First (CSPF) calculations that respect bandwidth and other constraints.

TE tunnels in RouterOS appear as interfaces. You can route traffic into them, assign IP addresses, and use them as transport for VPLS or MPLS VPNs. They are unidirectional - if you need bidirectional communication, create tunnels in both directions.

MPLS-TE solves specific problems that standard routing cannot:

ScenarioWhy TE Helps
Link utilization imbalanceRoute traffic away from congested paths
Latency-sensitive applicationsForce traffic over lower-latency links
Bandwidth guaranteesReserve capacity along specific paths
Disaster recoveryPre-establish backup paths through alternate routes
Multi-tenant isolationSeparate customer traffic onto different physical paths

When NOT to use MPLS-TE: If your network is small, has uniform link capacity, or doesn’t require explicit path control, standard LDP-based MPLS is simpler and sufficient.

An LSP is the path that MPLS-labeled packets follow through the network. With TE, you control this path rather than leaving it to the IGP.

Head-End Tail-End
R1 ──[Push Label]──→ R2 ──[Swap Label]──→ R3 ──[Pop Label]──→ R4
TE Tunnel Interface Tunnel Destination

RSVP-TE establishes the tunnel by sending Path messages from head-end to tail-end, then Resv messages back confirming the reservation. This process:

  1. Reserves resources (bandwidth) along the path
  2. Distributes labels at each hop
  3. Establishes the LSP

Explicit Path: You define every hop the tunnel must traverse.

  • Use when you need guaranteed routing through specific nodes
  • Requires knowing your network topology

Dynamic Path (CSPF): RouterOS calculates the path based on constraints.

  • Use when you want constraint-based routing without manual hop specification
  • Requires OSPF with TE extensions enabled

Before creating tunnels, enable Traffic Engineering on interfaces that will participate in TE paths:

# RouterOS 6.x syntax
/mpls traffic-eng interface add interface=ether1 bandwidth=1000000000
/mpls traffic-eng interface add interface=ether2 bandwidth=1000000000
# RouterOS 7.x syntax
/mpls/traffic-eng/interface/add interface=ether1 bandwidth=1000000000
/mpls/traffic-eng/interface/add interface=ether2 bandwidth=1000000000

The bandwidth parameter is administrative - it tells CSPF how much capacity is available for path calculations. Set it to your link speed or the capacity you want to advertise.

If using dynamic CSPF paths, OSPF must distribute TE information:

# RouterOS 6.x
/routing ospf instance set default mpls-te-area=backbone mpls-te-router-id=10.255.255.1
# RouterOS 7.x
/routing/ospf/instance/set default mpls-te-area=backbone mpls-te-router-id=10.255.255.1
  • mpls-te-area: The OSPF area where TE opaque LSAs are flooded
  • mpls-te-router-id: Usually your loopback address; identifies this router in TE

Apply this configuration on ALL routers in the TE domain.

Define how the tunnel should be routed:

Option A: Dynamic Path Using CSPF

/mpls traffic-eng tunnel-path add name=dynamic-to-r4 use-cspf=yes

CSPF calculates the path automatically based on available bandwidth and link metrics.

Option B: Explicit Path with Strict Hops

/mpls traffic-eng tunnel-path add name=explicit-to-r4 use-cspf=no \
hops=192.168.12.2:strict,192.168.23.2:strict,192.168.34.2:strict

With strict hops, packets must traverse directly between the specified addresses - they must be adjacent routers.

Option C: Explicit Path with Loose Hops

/mpls traffic-eng tunnel-path add name=loose-to-r4 use-cspf=no \
hops=10.255.255.2:loose,192.168.34.2:strict

Loose hops allow intermediate routers between specified points. The last hop should typically be strict and use the interface IP (not loopback) of the destination.

/interface traffic-eng add name=te-to-r4 \
to-address=10.255.255.4 \
bandwidth=100000000 \
primary-path=dynamic-to-r4 \
disabled=no
  • to-address: The tail-end router’s address (usually loopback)
  • bandwidth: Bandwidth to reserve (administrative, affects CSPF calculations on other tunnels)
  • primary-path: Reference to the tunnel-path entry

Tunnels are disabled by default. Enable after configuration:

/interface traffic-eng enable te-to-r4

Consider this network topology:

R1 ────────── R2
│ │
│ │
R4 ────────── R3

Goal: Create a TE tunnel from R1 to R3 that goes through R2 (avoiding the R1-R4-R3 path).

# Enable TE on interfaces
/mpls traffic-eng interface
add interface=ether1-to-r2 bandwidth=1000000000
add interface=ether2-to-r4 bandwidth=1000000000
# Configure OSPF for TE
/routing ospf instance set default mpls-te-area=backbone mpls-te-router-id=10.255.255.1
# Create explicit path through R2
/mpls traffic-eng tunnel-path add name=via-r2 use-cspf=no \
hops=192.168.12.2:strict,192.168.23.2:strict
# Create TE tunnel
/interface traffic-eng add name=te-to-r3 \
to-address=10.255.255.3 \
bandwidth=100000000 \
primary-path=via-r2 \
record-route=yes \
disabled=no
# Enable TE on interfaces
/mpls traffic-eng interface
add interface=ether1-to-r1 bandwidth=1000000000
add interface=ether2-to-r3 bandwidth=1000000000
# Configure OSPF for TE
/routing ospf instance set default mpls-te-area=backbone mpls-te-router-id=10.255.255.2
# Enable TE on interfaces
/mpls traffic-eng interface
add interface=ether1-to-r2 bandwidth=1000000000
add interface=ether2-to-r4 bandwidth=1000000000
# Configure OSPF for TE
/routing ospf instance set default mpls-te-area=backbone mpls-te-router-id=10.255.255.3
# Enable TE on interfaces (for OSPF TE database completeness)
/mpls traffic-eng interface
add interface=ether1-to-r1 bandwidth=1000000000
add interface=ether2-to-r3 bandwidth=1000000000
# Configure OSPF for TE
/routing ospf instance set default mpls-te-area=backbone mpls-te-router-id=10.255.255.4

For resilience, configure a secondary path that activates if the primary fails:

# Create backup path (dynamic, will find any available route)
/mpls traffic-eng tunnel-path add name=backup-dynamic use-cspf=yes
# Update tunnel with secondary path
/interface traffic-eng set te-to-r3 \
secondary-paths=backup-dynamic \
primary-retry-interval=30s

When the primary path fails (link down, RSVP timeout), the tunnel switches to the secondary path. The primary-retry-interval controls how often RouterOS attempts to re-establish the primary.

TE tunnels appear as interfaces. To use them:

/ip route add dst-address=10.100.0.0/24 gateway=te-to-r3
/ip address add address=172.16.0.1/30 interface=te-to-r3

Then establish routing (static or dynamic) over the tunnel.

/interface vpls add name=vpls1 remote-peer=10.255.255.3 use-explicit-path=te-to-r3
/mpls traffic-eng interface print

Expected Output:

Flags: X - disabled
# INTERFACE BANDWIDTH
0 ether1-to-r2 1000000000
1 ether2-to-r4 1000000000
/interface traffic-eng print

Expected Output:

Flags: X - disabled, R - running
# NAME TO-ADDRESS BANDWIDTH PRIMARY-PATH ACTUAL-PATH
0 R te-to-r3 10.255.255.3 100000000 via-r2 via-r2

The R flag indicates the tunnel is running (established).

/interface traffic-eng monitor te-to-r3 once

Expected Output:

tunnel-id: 1
primary-path-state: established
secondary-path-state: not-configured
active-path: via-r2
active-lspid: 1
active-label: 18
explicit-route: 192.168.12.2->192.168.23.2
recorded-route: 192.168.12.2[18]->192.168.23.2[impl-null]
reserved-bandwidth: 100000000

Key fields:

  • primary-path-state: established - Tunnel is up
  • explicit-route - The path being used
  • recorded-route - Actual path with labels
/routing ospf instance print

Expected Output:

name: default
mpls-te-area: backbone
mpls-te-router-id: 10.255.255.1
/mpls forwarding-table print

Expected Output: Should show label bindings for the tunnel.

Problem: “Tunnel stuck on hold, never establishes”

Section titled “Problem: “Tunnel stuck on hold, never establishes””

Cause: RSVP protocol not running on intermediate routers.

Solution:

  1. Verify all routers along the path have TE interfaces configured
  2. For mixed vendor networks (e.g., Cisco), ensure RSVP is enabled:
    ! Cisco IOS
    interface GigabitEthernet0/0
    ip rsvp bandwidth
    mpls traffic-eng tunnels
  3. Check RSVP neighbors: /mpls rsvp interface print

Cause: OSPF not distributing TE information or bandwidth exhausted.

Solution:

  1. Verify OSPF TE configuration on all routers:
    /routing ospf instance print
    Must show mpls-te-area and mpls-te-router-id
  2. Check available bandwidth:
    /mpls traffic-eng interface print
  3. Reduce tunnel bandwidth requirement or increase interface bandwidth

Problem: “Tunnel establishes but traffic doesn’t flow”

Section titled “Problem: “Tunnel establishes but traffic doesn’t flow””

Cause: Routing not configured to use the tunnel.

Solution:

  1. Add static route pointing to tunnel interface:
    /ip route add dst-address=DESTINATION gateway=te-tunnel-name
  2. Or assign IP to tunnel and configure dynamic routing

Cause: CSPF bug in some RouterOS versions or metric misconfiguration.

Solution:

  1. Use explicit path with loose hops to constrain the route:
    /mpls traffic-eng tunnel-path set [find name=my-path] \
    hops=INTERMEDIATE_ROUTER:loose,FINAL_HOP:strict
  2. Upgrade RouterOS if using an older version

Problem: “Last hop in explicit path rejected”

Section titled “Problem: “Last hop in explicit path rejected””

Cause: Last hop must be interface IP of destination router, not loopback.

Solution: Use the actual interface IP that receives traffic on the tail-end router:

# Wrong - loopback as last hop
hops=192.168.12.2:strict,10.255.255.3:strict
# Correct - interface IP as last hop
hops=192.168.12.2:strict,192.168.23.2:strict

Cause: TE bandwidth is administrative only - RSVP reserves it for path calculations but doesn’t police traffic.

Solution: Add queue to limit actual traffic:

/queue simple add name=te-limit target=te-to-r3 max-limit=100M/100M

Wrong: Expecting return traffic to use the same path

# Only creates tunnel R1 → R3
/interface traffic-eng add name=te-to-r3 to-address=10.255.255.3 ...

Right: Create tunnels in both directions

# On R1: tunnel to R3
/interface traffic-eng add name=te-to-r3 to-address=10.255.255.3 ...
# On R3: tunnel to R1
/interface traffic-eng add name=te-to-r1 to-address=10.255.255.1 ...

Wrong: Loopback address as final hop

/mpls traffic-eng tunnel-path add name=path1 hops=192.168.12.2:strict,10.255.255.3:strict

Right: Interface IP as final hop

/mpls traffic-eng tunnel-path add name=path1 hops=192.168.12.2:strict,192.168.23.2:strict

Wrong: Creating tunnels without OSPF TE

# No mpls-te-area configured - CSPF won't work
/interface traffic-eng add name=te1 to-address=10.255.255.3 primary-path=dynamic-path

Right: Configure OSPF TE first

/routing ospf instance set default mpls-te-area=backbone mpls-te-router-id=10.255.255.1

Wrong: Thinking reserved bandwidth enforces limits

# This doesn't actually limit traffic to 100Mbps
/interface traffic-eng add name=te1 bandwidth=100000000 ...

Right: Add queues for traffic policing

/interface traffic-eng add name=te1 bandwidth=100000000 ...
/queue simple add name=te1-limit target=te1 max-limit=100M/100M

Wrong: Using v6 syntax in v7

/mpls traffic-eng interface add interface=ether1 # Fails in v7

Right: Use v7 slash syntax

/mpls/traffic-eng/interface/add interface=ether1

RouterOS can automatically adjust tunnel bandwidth based on actual usage:

/interface traffic-eng set te-to-r3 \
auto-bandwidth-avg-interval=5m \
auto-bandwidth-update-interval=1h
  • auto-bandwidth-avg-interval: Window for calculating average traffic
  • auto-bandwidth-update-interval: How often to update the reservation

Force the tunnel to recalculate its path:

# Manual reoptimization
/interface traffic-eng reoptimize te-to-r3
# Automatic reoptimization
/interface traffic-eng set te-to-r3 reoptimize-interval=5m

Control which tunnels can preempt others when bandwidth is scarce:

/interface traffic-eng set te-to-r3 \
setup-priority=3 \
holding-priority=3
  • Priority 0 is highest (can preempt anything)
  • Priority 7 is lowest (can be preempted by anything)
  • setup-priority: Ability to preempt existing tunnels
  • holding-priority: Resistance to being preempted
  • No Fast Reroute: RouterOS doesn’t support MPLS local protection. Failover relies on RSVP re-signaling (seconds, not milliseconds)
  • No Link/Node Protection: Pre-established backup paths at transit routers not supported
  • Administrative Bandwidth: Doesn’t reflect actual link capacity or enforce traffic limits
  • IPv4 Only: IPv6 TE tunnel support is limited/experimental
  • Documentation Gaps: Some v7 features may not be fully documented
  • OSPF - required for CSPF
  • BGP - BGP over MPLS-TE tunnels
  • Static Routes - routing traffic into tunnels
  • VRRP - gateway redundancy
  • BFD - fast failure detection