Policy-Based Routing (PBR) — Override the Routing Table with Route Maps
Standard IP routing has one decision criterion: the destination IP address. The router looks up the destination in its routing table and forwards the packet toward the best-matching prefix — regardless of where the packet came from, what protocol it carries, or what port it is destined for. This works well for most traffic, but modern networks increasingly require more nuanced forwarding decisions. A company with two ISP connections wants HTTP traffic from branch offices to use the cheaper broadband link and voice-over-IP to use the lower-latency MPLS link. A data centre operator wants database queries from application servers to use a direct path while management traffic uses a separate out-of-band path. A service provider needs to steer traffic from different customers to different next-hops based on source subnet.
Policy-Based Routing (PBR) extends the routing decision beyond
the destination address. Using a route-map as
the policy engine and the ip policy route-map
command as the enforcement point, PBR evaluates each incoming
packet against match criteria (source IP, packet length,
protocol, IP DSCP, IP precedence, or any combination) and
applies set actions (next-hop IP, output interface, IP
precedence rewrite) before the normal routing table lookup
occurs. Packets that match PBR policy are forwarded according
to the policy; packets that do not match fall through to normal
destination-based routing.
For routing protocols that interact with PBR decisions see OSPF Single-Area Configuration and BGP Basics (eBGP) — in multi-ISP scenarios, PBR is often combined with BGP for complete inbound and outbound traffic control. For QoS actions that can be combined with PBR see DSCP Marking & Classification. For route filtering using the same route-map syntax see Route Summarization & Aggregation.
1. Core Concepts — How PBR Works
Normal Routing vs Policy-Based Routing
NORMAL DESTINATION-BASED ROUTING:
─────────────────────────────────
Packet arrives on interface
│
▼
Look up DESTINATION IP in routing table
│
▼
Forward toward best matching prefix
(longest match wins — source, protocol, port ignored)
─────────────────────────────────────────────────────────────────────
POLICY-BASED ROUTING (PBR):
─────────────────────────────
Packet arrives on interface
│
▼
┌─────────────────────────────────────────────────┐
│ ip policy route-map [name] on INGRESS interface│ ← PBR applied here
└─────────────────────────────────────────────────┘
│
▼
Evaluate route-map clauses in sequence order
┌──────────────────────────────┐
│ route-map PBR_POLICY seq 10 │
│ match ip address ACL-VoIP │ ← Match criterion
│ set ip next-hop 10.0.1.1 │ ← Policy action
└──────────────┬───────────────┘
│ Match? → Forward to 10.0.1.1 (bypass routing table)
│ No match ↓
┌──────────────────────────────┐
│ route-map PBR_POLICY seq 20 │
│ match ip address ACL-HTTP │
│ set ip next-hop 203.0.1.1 │
└──────────────┬───────────────┘
│ Match? → Forward to 203.0.1.1
│ No match ↓
┌──────────────────────────────┐
│ Implicit deny (no more seqs) │
│ → Fall through to normal │
│ destination-based routing │
└──────────────────────────────┘
KEY BEHAVIOURS:
• PBR is evaluated BEFORE the routing table — it overrides dest-based routing
• PBR is applied to INGRESS traffic on a specific interface (NOT egress)
• Packets that DO NOT match any PBR clause are routed normally (no drop)
• The set action can specify: next-hop IP, output interface, or both
• Local router traffic uses 'ip local policy route-map' (separate command)
Route-Map Structure for PBR
ROUTE-MAP ANATOMY: route-map [NAME] [permit|deny] [sequence-number] match [criteria] ← what to match set [action] ← what to do when matched PERMIT clause: if match criteria are met → apply set action DENY clause: if match criteria are met → drop packet (rare in PBR) No match: try next sequence; if none → fall through to routing table ┌──────────────────────────────────────────────────────────────────┐ │ PBR MATCH OPTIONS │ ├──────────────────────────────────────────────────────────────────┤ │ match ip address [acl-name|acl-number] │ │ → match source AND/OR destination IP, protocol, port (via ACL)│ │ │ │ match length [min] [max] │ │ → match packet size in bytes (useful for MTU-based policies) │ │ │ │ match ip dscp [dscp-value] │ │ → match DSCP marking in IP header │ │ │ │ match ip precedence [value] │ │ → match IP Precedence bits (legacy) │ └──────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────┐ │ PBR SET OPTIONS │ ├──────────────────────────────────────────────────────────────────┤ │ set ip next-hop [ip-address] [ip-address2 ...] │ │ → forward to specified next-hop IP │ │ → multiple IPs = failover (try first, if unreachable try next)│ │ │ │ set ip next-hop verify-availability [ip] [track-obj] [ip2] ... │ │ → only use next-hop if IP SLA track object is reachable │ │ → provides automatic failover when ISP link goes down │ │ │ │ set interface [interface-type] [interface-number] │ │ → send out specific interface (for unnumbered/NBMA links) │ │ │ │ set ip default next-hop [ip-address] │ │ → use as next-hop ONLY if routing table has no specific route │ │ → routing table takes precedence; policy is fallback │ │ │ │ set default interface [interface] │ │ → use interface ONLY if routing table has no specific route │ │ │ │ set ip precedence [value] │ │ → rewrite IP Precedence bits (QoS marking) │ │ │ │ set ip dscp [dscp-value] │ │ → rewrite DSCP bits (QoS marking while routing) │ └──────────────────────────────────────────────────────────────────┘
set ip next-hop vs set ip default next-hop
| Command | Routing Table Priority | When Applied | Use Case |
|---|---|---|---|
set ip next-hop [ip] |
PBR overrides routing table | Always applied when match succeeds — regardless of routing table | Hard policy enforcement — send traffic to a specific next-hop unconditionally. Multi-ISP forced routing. |
set ip default next-hop [ip] |
Routing table has priority | Applied only when no matching route exists in routing table | Flexible default — use routing table when a specific route exists, fall back to PBR next-hop only for unknown destinations. Default-route override. |
set interface [int] |
PBR overrides routing table | Always applied — sends out the specified interface | Point-to-point serial links, unnumbered interfaces. Risky on multi-access segments (no ARP resolution). |
set ip next-hop verify-availability |
PBR overrides routing table, with failover | Applied only if IP SLA tracking confirms next-hop reachability | Redundant multi-ISP — automatically fail over to backup ISP when primary goes down. |
ip cef). Always verify CEF is enabled before
deploying PBR in a production environment. CEF PBR is
sometimes called fast-path PBR and processes
traffic at line rate without CPU involvement.
2. Lab Topology — Multi-ISP Traffic Engineering
┌────────────────────────────────────────────────────┐
│ INTERNET │
└───────┬──────────────────────────┬─────────────────┘
│ │
ISP-A (MPLS/Leased) ISP-B (Broadband)
Low latency, high cost High bandwidth, low cost
203.0.113.1/30 198.51.100.1/30
│ │
Gi0/0 │ │ Gi0/1
┌──────┴──────────────────────────┴──────┐
│ NetsTuts_R1 │
│ Gi0/0: 203.0.113.2/30 (ISP-A) │
│ Gi0/1: 198.51.100.2/30 (ISP-B) │
│ Gi0/2: 10.0.0.1/24 (LAN) │
└──────────────────┬─────────────────────┘
│ Gi0/2
┌───────┴────────┐
│ LAN Switch │
└────┬──────┬────┘
10.0.0.10 10.0.0.20
┌──────┐ ┌──────┐
│ PC-A │ │ PC-B │
│ Exec │ │ Bulk │
│ VoIP │ │ HTTP │
└──────┘ └──────┘
PBR POLICY GOALS:
┌────────────────────────────────────────────────────────────────────┐
│ Rule 1: VoIP traffic (UDP dst 5060, 16384-32767) from any source │
│ → route via ISP-A (203.0.113.1) — low latency MPLS │
│ │
│ Rule 2: HTTP/HTTPS traffic (TCP dst 80, 443) from any source │
│ → route via ISP-B (198.51.100.1) — high bandwidth │
│ │
│ Rule 3: Traffic from 10.0.0.0/28 (executive subnet) │
│ → route via ISP-A (203.0.113.1) regardless of protocol │
│ │
│ Rule 4: All other traffic │
│ → normal routing table (default route via ISP-A) │
└────────────────────────────────────────────────────────────────────┘
3. Step 1 — Create Access Lists for PBR Match Criteria
PBR uses standard or extended ACLs as the match criteria in route-map clauses. The ACL defines what to match — the route-map then applies the set action to matched traffic. Critically, ACL permit statements mean "match this traffic for PBR" and ACL deny statements mean "do not match this traffic — let it fall through." The ACL is never used for actual permit/deny forwarding decisions when used inside a route-map match statement. For a full overview of ACLs see ACL Overview, Standard ACL Configuration, and Extended ACL Configuration.
ACL for VoIP Traffic (SIP + RTP)
! ── ACL matching VoIP: SIP signalling (UDP 5060) + RTP media ───── ! ── RTP uses dynamic ports 16384–32767 (Cisco default range) ────── NetsTuts_R1(config)#ip access-list extended ACL-VOIP NetsTuts_R1(config-ext-nacl)#remark Match SIP signalling UDP 5060 NetsTuts_R1(config-ext-nacl)#permit udp any any eq 5060 NetsTuts_R1(config-ext-nacl)#remark Match RTP media streams UDP 16384-32767 NetsTuts_R1(config-ext-nacl)#permit udp any any range 16384 32767 NetsTuts_R1(config-ext-nacl)#exit
ACL for HTTP/HTTPS Traffic
! ── ACL matching HTTP and HTTPS ────────────────────────────────── NetsTuts_R1(config)#ip access-list extended ACL-WEB NetsTuts_R1(config-ext-nacl)#remark Match HTTP NetsTuts_R1(config-ext-nacl)#permit tcp any any eq 80 NetsTuts_R1(config-ext-nacl)#remark Match HTTPS NetsTuts_R1(config-ext-nacl)#permit tcp any any eq 443 NetsTuts_R1(config-ext-nacl)#exit
ACL for Executive Subnet (Source-Based Routing)
! ── Standard ACL matching source IP of executive subnet ────────── ! ── (source-based routing — all traffic from this subnet via ISP-A) NetsTuts_R1(config)#ip access-list standard ACL-EXEC-SUBNET NetsTuts_R1(config-std-nacl)#remark Executive subnet 10.0.0.0/28 NetsTuts_R1(config-std-nacl)#permit 10.0.0.0 0.0.0.15 NetsTuts_R1(config-std-nacl)#exit
match ip address
statements, you can reference either standard or extended ACLs.
See Wildcard Masks for
help with subnet wildcard notation used in ACL entries.
Verify ACLs Before Applying to Route-Map
NetsTuts_R1#show ip access-lists
Extended IP access list ACL-VOIP
10 permit udp any any eq 5060
20 permit udp any any range 16384 32767
Extended IP access list ACL-WEB
10 permit tcp any any eq 80
20 permit tcp any any eq 443
Standard IP access list ACL-EXEC-SUBNET
10 permit 10.0.0.0, wildcard bits 0.0.0.15
4. Step 2 — Build the PBR Route-Map
The route-map is the policy engine. Each sequence number is a separate rule evaluated in ascending order. When a packet matches a clause, the corresponding set action is applied and no further clauses are evaluated (first match wins). Sequences with no match statement match all traffic — only use this intentionally as a catch-all.
Sequence 10 — VoIP to ISP-A (Low Latency)
NetsTuts_R1(config)#route-map PBR-MULTI-ISP permit 10 NetsTuts_R1(config-route-map)#description VoIP-via-ISP-A-low-latency NetsTuts_R1(config-route-map)#match ip address ACL-VOIP NetsTuts_R1(config-route-map)#set ip next-hop 203.0.113.1 NetsTuts_R1(config-route-map)#exit
Sequence 20 — HTTP/HTTPS to ISP-B (High Bandwidth)
NetsTuts_R1(config)#route-map PBR-MULTI-ISP permit 20 NetsTuts_R1(config-route-map)#description Web-traffic-via-ISP-B-broadband NetsTuts_R1(config-route-map)#match ip address ACL-WEB NetsTuts_R1(config-route-map)#set ip next-hop 198.51.100.1 NetsTuts_R1(config-route-map)#exit
Sequence 30 — Executive Subnet to ISP-A (Source-Based)
NetsTuts_R1(config)#route-map PBR-MULTI-ISP permit 30 NetsTuts_R1(config-route-map)#description Executive-subnet-via-ISP-A NetsTuts_R1(config-route-map)#match ip address ACL-EXEC-SUBNET NetsTuts_R1(config-route-map)#set ip next-hop 203.0.113.1 NetsTuts_R1(config-route-map)#exit
No Sequence 40 Needed — Implicit Fall-Through
! ── No explicit "match all → normal routing" needed ─────────────── ! ── Packets that do not match sequence 10, 20, or 30 automatically ! ── fall through to the normal routing table lookup ──────────────── ! ── This is the correct behaviour — PBR only intercepts matched traffic ! ── WRONG approach (do not do this): ───────────────────────────── ! route-map PBR-MULTI-ISP permit 40 ! (no match statement) ← matches ALL traffic ! set ip next-hop 203.0.113.1 ! ← This would override routing for ALL unmatched traffic, ! including management traffic, routing protocol updates, ! and traffic that should use the local routing table. ! Only add a catch-all if you explicitly want to force ! all traffic through a specific path.
View the Route-Map Configuration
NetsTuts_R1#show route-map PBR-MULTI-ISP
route-map PBR-MULTI-ISP, permit, sequence 10
Match clauses:
ip address (access-lists): ACL-VOIP
Set clauses:
ip next-hop 203.0.113.1
Policy routing matches: 0 packets, 0 bytes
route-map PBR-MULTI-ISP, permit, sequence 20
Match clauses:
ip address (access-lists): ACL-WEB
Set clauses:
ip next-hop 198.51.100.1
Policy routing matches: 0 packets, 0 bytes
route-map PBR-MULTI-ISP, permit, sequence 30
Match clauses:
ip address (access-lists): ACL-EXEC-SUBNET
Set clauses:
ip next-hop 203.0.113.1
Policy routing matches: 0 packets, 0 bytes
5. Step 3 — Apply PBR to the Ingress Interface
PBR is applied to the ingress (inbound) direction of the interface where traffic arrives. In this topology, all LAN traffic from PC-A and PC-B arrives on Gi0/2. The route-map is applied to Gi0/2 inbound — this intercepts LAN traffic as it enters the router, before the routing table lookup.
! ── Verify CEF is enabled (required for fast-path PBR) ────────── NetsTuts_R1#show ip cef Prefix Next Hop Interface 0.0.0.0/0 203.0.113.1 GigabitEthernet0/0 10.0.0.0/24 attached GigabitEthernet0/2 ... ! ── CEF is active (prefixes shown in FIB) ──────────────────────── ! ── Apply PBR to the LAN-facing interface ─────────────────────── NetsTuts_R1(config)#interface GigabitEthernet0/2 NetsTuts_R1(config-if)#description LAN-Interface-PBR NetsTuts_R1(config-if)#ip address 10.0.0.1 255.255.255.0 NetsTuts_R1(config-if)#ip policy route-map PBR-MULTI-ISP ! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ! This single command activates PBR on this interface NetsTuts_R1(config-if)#no shutdown NetsTuts_R1(config-if)#exit ! ── Verify PBR is applied ──────────────────────────────────────── NetsTuts_R1#show ip interface GigabitEthernet0/2 GigabitEthernet0/2 is up, line protocol is up Internet address is 10.0.0.1/24 ... Policy routing is enabled, using route map PBR-MULTI-ISP ← ✓ ...
ip policy route-map command only functions
in the inbound direction.
Default Routes for Non-PBR Traffic
Non-PBR traffic falls through to the routing table. Configure default routes and optionally floating static routes for ISP backup. See also Static Routing Configuration.
! ── Non-PBR traffic uses the routing table — configure default routes NetsTuts_R1(config)#ip route 0.0.0.0 0.0.0.0 203.0.113.1 name Default-ISP-A ! ── All unmatched traffic goes to ISP-A by default via routing table ! ── Optionally add ISP-B default as floating route (higher AD) ──── NetsTuts_R1(config)#ip route 0.0.0.0 0.0.0.0 198.51.100.1 10 name Backup-ISP-B ! ^^ ! AD 10 = floating static (default AD=1) ! Only used if ISP-A default is removed
6. Step 4 — PBR with IP SLA Failover (verify-availability)
The basic set ip next-hop has a critical
limitation: if the specified next-hop becomes unreachable
(ISP link down, ISP router offline), PBR still tries to
forward traffic to that dead next-hop — dropping all matched
traffic instead of failing over to the backup path. The
set ip next-hop verify-availability command
solves this by linking the next-hop decision to an
IP SLA
tracking object.
Configure IP SLA Probes to Monitor ISP Reachability
! ── IP SLA 1: Monitor ISP-A next-hop (203.0.113.1) ───────────────
NetsTuts_R1(config)#ip sla 1
NetsTuts_R1(config-ip-sla)#icmp-echo 203.0.113.1 source-interface GigabitEthernet0/0
NetsTuts_R1(config-ip-sla-echo)#frequency 5
! ^
! Send ICMP probe every 5 seconds
NetsTuts_R1(config-ip-sla-echo)#exit
NetsTuts_R1(config)#ip sla schedule 1 life forever start-time now
! ── IP SLA 2: Monitor ISP-B next-hop (198.51.100.1) ─────────────
NetsTuts_R1(config)#ip sla 2
NetsTuts_R1(config-ip-sla)#icmp-echo 198.51.100.1 source-interface GigabitEthernet0/1
NetsTuts_R1(config-ip-sla-echo)#frequency 5
NetsTuts_R1(config-ip-sla-echo)#exit
NetsTuts_R1(config)#ip sla schedule 2 life forever start-time now
! ── Create tracking objects tied to SLA results ──────────────────
NetsTuts_R1(config)#track 1 ip sla 1 reachability
! ^^^^^^^^^^^^^^^^^^^^^^^
! Track obj 1 = UP when SLA 1 ICMP succeeds (ISP-A alive)
NetsTuts_R1(config)#track 2 ip sla 2 reachability
! Track obj 2 = UP when SLA 2 ICMP succeeds (ISP-B alive)
! ── Verify tracking objects ──────────────────────────────────────
NetsTuts_R1#show track
Track 1
IP SLA 1 reachability
Reachability is Up
1 change, last change 00:05:23
Tracked by:
Route Map 0
Track 2
IP SLA 2 reachability
Reachability is Up
1 change, last change 00:05:21
Update Route-Map to Use verify-availability
! ── Rewrite the route-map with verify-availability failover ────── ! ── Sequence 10: VoIP → ISP-A (track 1), failover to ISP-B (track 2) NetsTuts_R1(config)#route-map PBR-MULTI-ISP permit 10 NetsTuts_R1(config-route-map)#description VoIP-ISP-A-with-failover NetsTuts_R1(config-route-map)#match ip address ACL-VOIP NetsTuts_R1(config-route-map)#set ip next-hop verify-availability 203.0.113.1 1 track 1 ! ^^^^^^^^^^^^ ^ ^^^^^^^ ! next-hop seq track-obj NetsTuts_R1(config-route-map)#set ip next-hop verify-availability 198.51.100.1 2 track 2 ! ↑ fallback: if track 1 down, use ISP-B NetsTuts_R1(config-route-map)#exit ! ── Sequence 20: Web → ISP-B (track 2), failover to ISP-A (track 1) NetsTuts_R1(config)#route-map PBR-MULTI-ISP permit 20 NetsTuts_R1(config-route-map)#description Web-ISP-B-with-failover NetsTuts_R1(config-route-map)#match ip address ACL-WEB NetsTuts_R1(config-route-map)#set ip next-hop verify-availability 198.51.100.1 1 track 2 NetsTuts_R1(config-route-map)#set ip next-hop verify-availability 203.0.113.1 2 track 1 NetsTuts_R1(config-route-map)#exit ! ── Sequence 30: Executive subnet → ISP-A with failover ────────── NetsTuts_R1(config)#route-map PBR-MULTI-ISP permit 30 NetsTuts_R1(config-route-map)#description Exec-subnet-ISP-A-failover NetsTuts_R1(config-route-map)#match ip address ACL-EXEC-SUBNET NetsTuts_R1(config-route-map)#set ip next-hop verify-availability 203.0.113.1 1 track 1 NetsTuts_R1(config-route-map)#set ip next-hop verify-availability 198.51.100.1 2 track 2 NetsTuts_R1(config-route-map)#exit
verify-availability syntax includes a
sequence number (1, 2) that determines priority among
multiple next-hops — lower sequence is tried first. When
track object 1 is Up (ISP-A reachable), VoIP traffic goes
to 203.0.113.1. If track 1 goes Down (ISP-A unreachable),
the router tries sequence 2: check track 2 (ISP-B) — if
Up, forward to 198.51.100.1. This provides automatic
failover with no manual intervention. The IP SLA probes
detect ISP failure within 5–15 seconds (3 missed probes
× 5-second interval), and PBR immediately adjusts routing.
7. Advanced PBR — Local Policy and Packet-Length Matching
Local PBR — Routing Traffic Originated by the Router Itself
Standard PBR (using ip policy route-map on an
interface) only affects transit traffic — packets
that arrive on the interface and are forwarded through the
router. Traffic originated by the router itself
(management traffic, routing protocol updates, pings
from the router) is NOT affected by interface PBR. To
apply PBR to locally originated traffic, use the global
command ip local policy route-map. Management
protocols commonly affected include
SSH,
SNMP, and
Syslog.
! ── Scenario: Route all router-generated management traffic ────── ! ── (SSH, SNMP, syslog) via ISP-A management interface ─────────── ! ── while transit traffic uses the normal PBR policy ───────────── ! ── ACL matching management protocols (SSH, SNMP, syslog) ──────── NetsTuts_R1(config)#ip access-list extended ACL-MGMT-TRAFFIC NetsTuts_R1(config-ext-nacl)#permit tcp any any eq 22 NetsTuts_R1(config-ext-nacl)#permit udp any any eq 161 NetsTuts_R1(config-ext-nacl)#permit udp any any eq 514 NetsTuts_R1(config-ext-nacl)#exit ! ── Route-map for local traffic ────────────────────────────────── NetsTuts_R1(config)#route-map LOCAL-PBR permit 10 NetsTuts_R1(config-route-map)#description Router-mgmt-traffic-via-ISP-A NetsTuts_R1(config-route-map)#match ip address ACL-MGMT-TRAFFIC NetsTuts_R1(config-route-map)#set ip next-hop 203.0.113.1 NetsTuts_R1(config-route-map)#exit ! ── Apply to locally-originated traffic (global command) ───────── NetsTuts_R1(config)#ip local policy route-map LOCAL-PBR ! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ! Note: 'ip local policy' not 'ip policy on interface' ! ── Verify local PBR ───────────────────────────────────────────── NetsTuts_R1#show ip local policy Local policy routing is enabled, using route map LOCAL-PBR ← ✓
PBR Based on Packet Length — MTU-Based Traffic Engineering
! ── Scenario: Large packets (>512 bytes) via ISP-A high-capacity ─ ! ── Small packets (<= 512 bytes) via ISP-B low-latency ─ ! ── (Common for separating bulk file transfer from interactive ─ ! ── traffic like SSH keystrokes, DNS queries, VoIP RTP) ─ NetsTuts_R1(config)#route-map PBR-BY-LENGTH permit 10 NetsTuts_R1(config-route-map)#description Large-packets-via-ISP-A NetsTuts_R1(config-route-map)#match length 513 1500 ! ^^^ ^^^^ ! min bytes max bytes NetsTuts_R1(config-route-map)#set ip next-hop 203.0.113.1 NetsTuts_R1(config-route-map)#exit NetsTuts_R1(config)#route-map PBR-BY-LENGTH permit 20 NetsTuts_R1(config-route-map)#description Small-packets-via-ISP-B NetsTuts_R1(config-route-map)#match length 0 512 NetsTuts_R1(config-route-map)#set ip next-hop 198.51.100.1 NetsTuts_R1(config-route-map)#exit ! ── Apply to LAN interface ─────────────────────────────────────── NetsTuts_R1(config)#interface GigabitEthernet0/2 NetsTuts_R1(config-if)#ip policy route-map PBR-BY-LENGTH NetsTuts_R1(config-if)#exit
PBR with DSCP Rewriting
! ── Scenario: Mark VoIP traffic with DSCP EF (46) while routing ── ! ── Combined QoS marking + routing decision in one policy ───────── NetsTuts_R1(config)#route-map PBR-VOIP-MARK permit 10 NetsTuts_R1(config-route-map)#match ip address ACL-VOIP NetsTuts_R1(config-route-map)#set ip next-hop 203.0.113.1 NetsTuts_R1(config-route-map)#set ip dscp ef ! ^^^^^^ ! DSCP EF (Expedited Forwarding = 46/0x2E) — voice class NetsTuts_R1(config-route-map)#exit NetsTuts_R1(config)#interface GigabitEthernet0/2 NetsTuts_R1(config-if)#ip policy route-map PBR-VOIP-MARK NetsTuts_R1(config-if)#exit
set ip next-hop and set ip
dscp in the same route-map clause lets you perform
both the routing decision and the QoS marking in a single
policy. This is efficient for voice traffic: mark with DSCP
EF (ensuring it gets priority treatment in downstream
QoS queues) AND send it via the low-latency ISP — both actions
in one route-map clause. This is more efficient than
running a separate policy-map for DSCP marking and
a route-map for routing.
8. Step 5 — Verification and Troubleshooting
show route-map — Policy Hit Counters
! ── Check route-map hit counters (most important PBR verify cmd) ──
NetsTuts_R1#show route-map PBR-MULTI-ISP
route-map PBR-MULTI-ISP, permit, sequence 10
Match clauses:
ip address (access-lists): ACL-VOIP
Set clauses:
ip next-hop verify-availability 203.0.113.1 1 track 1 [up] ← ✓ track Up
ip next-hop verify-availability 198.51.100.1 2 track 2 [up]
Policy routing matches: 1842 packets, 921000 bytes ← ✓ traffic matched
route-map PBR-MULTI-ISP, permit, sequence 20
Match clauses:
ip address (access-lists): ACL-WEB
Set clauses:
ip next-hop verify-availability 198.51.100.1 1 track 2 [up]
ip next-hop verify-availability 203.0.113.1 2 track 1 [up]
Policy routing matches: 24531 packets, 18398250 bytes ← ✓ web traffic matched
route-map PBR-MULTI-ISP, permit, sequence 30
Match clauses:
ip address (access-lists): ACL-EXEC-SUBNET
Set clauses:
ip next-hop verify-availability 203.0.113.1 1 track 1 [up]
ip next-hop verify-availability 198.51.100.1 2 track 2 [up]
Policy routing matches: 543 packets, 271500 bytes
show ip policy — Interfaces with Active PBR
NetsTuts_R1#show ip policy Interface Route map Gi0/2 PBR-MULTI-ISP ← ✓ PBR active on LAN interface Local LOCAL-PBR ← ✓ Local policy active
debug ip policy — Live Traffic Tracing
! ── WARNING: debug ip policy generates output for EVERY PBR decision
! ── Use only in lab or during low-traffic maintenance windows ──────
! ── On high-traffic production routers this WILL impact performance ─
NetsTuts_R1#debug ip policy
Policy routing debugging is on
! ── Generate test traffic from PC-A (simulate VoIP UDP 5060) ─────
! ── [Console output from debug] ──────────────────────────────────
IP: s=10.0.0.10 (GigabitEthernet0/2), d=8.8.8.8, len 100, policy match
IP: route map PBR-MULTI-ISP, item 10, permit
IP: s=10.0.0.10 (GigabitEthernet0/2), d=8.8.8.8
g=203.0.113.1 (GigabitEthernet0/0), forward ← ✓ UDP 5060 → ISP-A
! ── HTTP traffic (simulate TCP dst 80) ───────────────────────────
IP: s=10.0.0.20 (GigabitEthernet0/2), d=172.217.0.0, len 500, policy match
IP: route map PBR-MULTI-ISP, item 20, permit
IP: s=10.0.0.20 (GigabitEthernet0/2), d=172.217.0.0
g=198.51.100.1 (GigabitEthernet0/1), forward ← ✓ TCP 80 → ISP-B
! ── Non-matched traffic (falls to routing table) ─────────────────
IP: s=10.0.0.10 (GigabitEthernet0/2), d=10.20.0.1, len 64, policy rejected
IP: route map PBR-MULTI-ISP, items not matched
! ← Traffic uses normal routing table (not dropped — just normal routing)
! ── Turn off debug when done ─────────────────────────────────────
NetsTuts_R1#undebug ip policy
Verify IP SLA and Tracking Status
NetsTuts_R1#show ip sla statistics
IPSLAs Latest Operation Statistics
IPSLA operation id: 1
Latest RTT: 12 milliseconds
Latest operation start time: 14:22:05.001 UTC Mar 7 2026
Latest operation return code: OK ← ✓ ISP-A SLA responding
Number of successes: 1234
Number of failures: 0
Operation time to live: Forever
IPSLA operation id: 2
Latest RTT: 3 milliseconds
Latest operation return code: OK ← ✓ ISP-B SLA responding
! ── Check tracking objects ───────────────────────────────────────
NetsTuts_R1#show track brief
Track Type Instance Parameter State Last Change
1 ip sla 1 reachability Up 00:20:33
2 ip sla 2 reachability Up 00:20:31
! ── Simulate ISP-A failure — observe failover ────────────────────
! ── (Shut down Gi0/0 to simulate ISP-A link failure) ─────────────
NetsTuts_R1(config)#interface GigabitEthernet0/0
NetsTuts_R1(config-if)#shutdown
NetsTuts_R1(config-if)#exit
! ── After ~15 seconds (3 failed SLA probes × 5s interval) ────────
NetsTuts_R1#show track brief
Track Type Instance Parameter State Last Change
1 ip sla 1 reachability Down 00:00:17 ← ISP-A down
2 ip sla 2 reachability Up 00:25:44
NetsTuts_R1#show route-map PBR-MULTI-ISP
route-map PBR-MULTI-ISP, permit, sequence 10
Set clauses:
ip next-hop verify-availability 203.0.113.1 1 track 1 [down] ← ISP-A down
ip next-hop verify-availability 198.51.100.1 2 track 2 [up] ← failover active
! ← VoIP traffic now automatically routing via ISP-B ────────────
Verification Command Summary
| Command | What It Shows | Key Field to Check |
|---|---|---|
show ip policy |
All interfaces with active PBR and their route-map names | Interface and route-map name must match configuration |
show route-map [name] |
Route-map clauses, match/set details, hit counters, track status | "Policy routing matches: N packets" — confirm traffic is being matched; track [up/down] status |
show ip interface [int] |
Interface IP config including active policy route-map | "Policy routing is enabled, using route map [name]" |
show ip local policy |
Route-map applied to locally-originated traffic | "Local policy routing is enabled, using route map [name]" |
show ip sla statistics |
IP SLA probe results — RTT and success/failure counts | Return code: OK = reachable; Timeout = unreachable |
show track brief |
Tracking object states — Up or Down | State column: Up = next-hop usable; Down = failover triggered |
debug ip policy |
Real-time per-packet PBR decision trace | "policy match" + "forward" = PBR applied; "policy rejected" = normal routing used |
show ip access-lists |
ACL hit counters for match criteria ACLs | Packet matches on permit entries confirm traffic is reaching the ACL |
9. Complete Configuration Reference & Key Points
Full PBR Configuration — NetsTuts_R1
! ════════════════ COMPLETE PBR CONFIGURATION ═════════════════════ ! ─── ACLs ──────────────────────────────────────────────────────── ip access-list extended ACL-VOIP remark Match SIP signalling permit udp any any eq 5060 remark Match RTP media permit udp any any range 16384 32767 ! ip access-list extended ACL-WEB remark Match HTTP permit tcp any any eq 80 remark Match HTTPS permit tcp any any eq 443 ! ip access-list standard ACL-EXEC-SUBNET remark Executive subnet permit 10.0.0.0 0.0.0.15 ! ! ─── IP SLA Probes ─────────────────────────────────────────────── ip sla 1 icmp-echo 203.0.113.1 source-interface GigabitEthernet0/0 frequency 5 ip sla schedule 1 life forever start-time now ! ip sla 2 icmp-echo 198.51.100.1 source-interface GigabitEthernet0/1 frequency 5 ip sla schedule 2 life forever start-time now ! ! ─── Track Objects ─────────────────────────────────────────────── track 1 ip sla 1 reachability track 2 ip sla 2 reachability ! ! ─── Route-Map ─────────────────────────────────────────────────── route-map PBR-MULTI-ISP permit 10 description VoIP-via-ISP-A-low-latency match ip address ACL-VOIP set ip next-hop verify-availability 203.0.113.1 1 track 1 set ip next-hop verify-availability 198.51.100.1 2 track 2 ! route-map PBR-MULTI-ISP permit 20 description Web-via-ISP-B-broadband match ip address ACL-WEB set ip next-hop verify-availability 198.51.100.1 1 track 2 set ip next-hop verify-availability 203.0.113.1 2 track 1 ! route-map PBR-MULTI-ISP permit 30 description Executive-subnet-via-ISP-A match ip address ACL-EXEC-SUBNET set ip next-hop verify-availability 203.0.113.1 1 track 1 set ip next-hop verify-availability 198.51.100.1 2 track 2 ! ! ─── Interface ─────────────────────────────────────────────────── interface GigabitEthernet0/0 description ISP-A-MPLS ip address 203.0.113.2 255.255.255.252 ! interface GigabitEthernet0/1 description ISP-B-Broadband ip address 198.51.100.2 255.255.255.252 ! interface GigabitEthernet0/2 description LAN-PBR-Interface ip address 10.0.0.1 255.255.255.0 ip policy route-map PBR-MULTI-ISP ← PBR applied here ! ! ─── Default Routes ────────────────────────────────────────────── ip route 0.0.0.0 0.0.0.0 203.0.113.1 name Default-ISP-A ip route 0.0.0.0 0.0.0.0 198.51.100.1 10 name Backup-ISP-B
PBR Command Reference
| Command | Mode | Purpose |
|---|---|---|
route-map [name] permit [seq] |
Global config | Create a route-map clause. Permit = apply set action when matched. Lower sequence evaluated first. |
match ip address [acl] |
Route-map config | Match traffic using standard or extended ACL. ACL permit = match for PBR; ACL deny = no match (fall through). |
match length [min] [max] |
Route-map config | Match based on IP packet size in bytes. Useful for separating bulk vs interactive traffic. |
match ip dscp [value] |
Route-map config | Match on DSCP bits in the IP header. Allows routing decisions based on existing QoS markings. |
set ip next-hop [ip] |
Route-map config | Override routing table — forward to specified next-hop unconditionally (if next-hop is reachable via CEF). |
set ip next-hop verify-availability [ip] [seq] track [n] |
Route-map config | Use next-hop only if tracking object is Up. Multiple entries with different sequences provide ordered failover. |
set ip default next-hop [ip] |
Route-map config | Use next-hop only if no matching route exists in routing table. Routing table takes priority. |
set interface [interface] |
Route-map config | Forward out specified interface. Use only on point-to-point links — unreliable on multi-access without ARP. |
set ip dscp [value] |
Route-map config | Rewrite DSCP bits while routing. Combines routing and QoS marking in a single policy. |
ip policy route-map [name] |
Interface config | Apply PBR to inbound traffic on the interface. Only affects transit traffic, not locally originated. |
ip local policy route-map [name] |
Global config | Apply PBR to traffic originated by the router itself (management, routing protocol packets). |
show ip policy |
Privileged exec | List all interfaces (and local) with active PBR route-maps. |
show route-map [name] |
Privileged exec | Display route-map clauses, hit counters, and tracking status. Primary PBR verification command. |
debug ip policy |
Privileged exec | Real-time per-packet PBR decision trace. Use with caution — high CPU impact on production routers. |
Key Points & Exam Tips
- PBR is applied to the ingress interface, not egress. The
ip policy route-mapcommand is configured on the interface where traffic enters the router — not the interface where it exits. Applying it to the wrong interface is the most common PBR misconfiguration. - PBR does not affect locally-originated traffic. Traffic generated by the router itself (ping from router, SSH sessions, routing protocol Hellos, SNMP traps) bypasses interface PBR entirely. Use
ip local policy route-mapat global config level to policy-route local traffic. - ACL permit in route-map match = "match this for PBR." When an ACL is used in a
match ip addressstatement,permitmeans "this traffic matches the PBR clause" anddenymeans "this traffic does not match — fall through." The ACL is not performing packet filtering — it is performing traffic classification. - Unmatched traffic falls through to normal routing — it is never dropped. If a packet does not match any route-map clause, it is forwarded normally using the routing table. PBR only intercepts and redirects matching traffic; non-matching traffic is unaffected.
set ip next-hopvsset ip default next-hop.set ip next-hopoverrides the routing table — the specified next-hop is used regardless of what is in the routing table.set ip default next-hopis a fallback — the routing table is checked first, and the PBR next-hop is only used if the routing table has no matching entry (no specific route). Use default next-hop for adding a PBR path without overriding existing specific routes.- Without verify-availability, PBR drops traffic when the next-hop is unreachable. Basic
set ip next-hopsends traffic to the configured next-hop regardless of whether it is actually reachable. If the ISP link is down, packets are forwarded to a dead gateway and dropped. Always useverify-availabilitywith IP SLA tracking in production multi-ISP deployments. - Route-map sequence numbers determine priority. Clauses are evaluated in ascending sequence order — lower numbers first. The first matching clause wins; subsequent clauses are not evaluated. Order your most specific or highest-priority policies with the lowest sequence numbers.
- PBR works in CEF mode for performance. On IOS routers with CEF enabled (
ip cef— the default), PBR is implemented as a CEF fast-path feature and processes traffic at line rate. Without CEF, PBR falls back to process switching — each packet interrupts the CPU. Always confirmshow ip cefshows an active FIB before deploying PBR in production. - On the CCNP exam: know the distinction between
ip policy route-map(interface, transit traffic) andip local policy(global, local traffic), the difference betweenset ip next-hopandset ip default next-hop, the role of ACL permit/deny in route-map match statements, and the verify-availability failover mechanism. Also review Administrative Distance, Default Routes, and QoS Overview as related topics.