VyOSXIII · Policy-Based RoutingPolicy-based routing
PBR for IPv6 — IPv6 source/destination matches, IPv6 next-hop, IPv6 interface
What you'll learn
- Configure IPv6 source/destination matches in a route-map for PBR
- Apply the route-map to an IPv6-enabled interface with `set interfaces ethernet <ifname> policy route-map6`
- Inspect the IPv6 ip rule and IPv6 routes in the PBR table
- Recognise the failure modes specific to IPv6 PBR (link-local next-hop, NDP, dual-stack policy)
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
PBR for IPv6 — IPv6 source/destination matches, IPv6 next-hop, IPv6 interface
PBR for IPv6 follows the same model as PBR for IPv4: a
route-map matches on packet criteria, sets attributes, and is
bound to an interface via FRR’s policy directive. The mechanics
are the same — ip rule, multiple routing tables, the rule
selector — but the syntax and the operational edge cases are
different. The IPv6 prefix-list is policy prefix-list6, the
interface binding is policy route-map6, the kernel view is
ip -6 rule show, and the next-hop is the IPv6 address.
The IPv6 PBR operator must reason about three edge cases that IPv4 PBR does not have: link-local next-hop, NDP (Neighbor Discovery Protocol), and the dual-stack pattern where both IPv4 and IPv6 traffic from the same subnet must take the same provider path. This lesson walks through the IPv6 route-map syntax, the interface binding, the operational commands, and the production failure modes the engineer must recognise.
IPv6 prefix-list
The IPv6 prefix-list is configured under set policy prefix-list6 rather than set policy prefix-list. The syntax
mirrors the IPv4 prefix-list with a rule number, an action, and
a prefix:
configure
set policy prefix-list6 PL-VOICE-SRC-V6 rule 10 action permit
set policy prefix-list6 PL-VOICE-SRC-V6 rule 10 prefix '2001:db8:10::/48'
commit
save
The prefix '2001:db8:10::/48' is the IPv6 prefix to match. The
rule 10 is the sequence number; multiple rules in the same
prefix-list are evaluated in order. The action permit accepts
matching prefixes; action deny rejects them.
The operator can verify with:
vyos@vyos:~$ show policy prefix-list6 PL-VOICE-SRC-V6
Prefix-list: PL-VOICE-SRC-V6
rule 10 {
action permit
prefix 2001:db8:10::/48
}
The output mirrors the IPv4 show policy prefix-list format.
IPv6 route-map with source/destination matches
The IPv6 route-map is configured under set policy route-map
with the match ip and set ip clauses — but the addresses
are IPv6 addresses. The VyOS configuration tree does not
distinguish between IPv4 and IPv6 route-maps by node; the
distinction is in the address family of the matched/next-hop
addresses.
configure
set policy prefix-list6 PL-VOICE-SRC-V6 rule 10 action permit
set policy prefix-list6 PL-VOICE-SRC-V6 rule 10 prefix '2001:db8:10::/48'
set policy route-map RM-VOICE-OUT-V6 rule 10 action permit
set policy route-map RM-VOICE-OUT-V6 rule 10 match ipv6 source address prefix-list6 PL-VOICE-SRC-V6
set policy route-map RM-VOICE-OUT-V6 rule 10 set ipv6 next-hop '2001:db8:ffff::1'
commit
save
The match ipv6 source address prefix-list6 PL-VOICE-SRC-V6
clause matches IPv6 packets with source in 2001:db8:10::/48.
The set ipv6 next-hop '2001:db8:ffff::1' clause sets the IPv6
next-hop. The ipv6 keyword (rather than ip) tells FRR to
use the IPv6 address family for the match and set clauses.
flowchart LR
P[IPv6 packet<br/>src=2001:db8:10::5<br/>dst=2001:db8:ffff::10] --> RM{Route-map<br/>RM-VOICE-OUT-V6}
RM -->|rule 10<br/>match ipv6 source PL-VOICE-SRC-V6| S[set ipv6 next-hop<br/>2001:db8:ffff::1]
S --> OUT[Egress eth2<br/>voice provider v6]
The FRR render:
ipv6 prefix-list PL-VOICE-SRC-V6 seq 10 permit 2001:db8:10::/48
route-map RM-VOICE-OUT-V6 permit 10
match ipv6 source-address prefix-list PL-VOICE-SRC-V6
set ipv6 next-hop 2001:db8:ffff::1
FRR renders the prefix-list6 clause as prefix-list (it
recognises the IPv6 prefix from the address family). The
operator can verify with:
vyos@vyos:~$ vtysh -c 'show route-map RM-VOICE-OUT-V6'
vyos@vyos:~$ vtysh -c 'show ipv6 prefix-list'
Binding the IPv6 route-map to an interface
The IPv6 interface binding uses policy route-map6 rather than
policy route-map. The syntax is otherwise the same:
configure
set interfaces ethernet eth1 policy route-map6 RM-VOICE-OUT-V6
commit
save
The policy route-map6 directive tells FRR to install an IPv6
ip -6 rule entry and populate an IPv6 PBR table with the
static routes the route-map generates. The commit engine
renders this to FRR’s ipv6 policy syntax.
After commit, the FRR configuration contains:
ipv6 prefix-list PL-VOICE-SRC-V6 seq 10 permit 2001:db8:10::/48
route-map RM-VOICE-OUT-V6 permit 10
match ipv6 source-address prefix-list PL-VOICE-SRC-V6
set ipv6 next-hop 2001:db8:ffff::1
ipv6 policy route-map RM-VOICE-OUT-V6
The ipv6 policy route-map directive is the IPv6 analogue of
the IPv4 ip policy route-map. FRR installs an IPv6 rule in
the kernel.
How the IPv6 PBR is validated
The validation command set for IPv6 PBR:
show policy route-map
show policy prefix-list6
show configuration commands | match 'policy route-map6'
ip -6 rule show
ip -6 route show table all
ip -6 route get <src> <dst>
The show policy route-map shows all configured route-maps
(both IPv4 and IPv6). The show policy prefix-list6 shows the
IPv6 prefix-lists. The show configuration commands | match
filter shows the IPv6 interface binding. The ip -6 rule show
shows the IPv6 rule installed in the kernel. The ip -6 route show table all shows the IPv6 routes in all tables. The ip -6 route get resolves the route for a specific source and
destination.
vyos@vyos:~$ ip -6 rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
vyos@vyos:~$ ip -6 route get 2001:db8:ffff::10 from 2001:db8:10::5 iif eth1
2001:db8:ffff::10 from 2001:db8:10::5 via 2001:db8:ffff::1 dev eth2 table 100 src 2001:db8:10::5
The ip -6 route get from a voice source returns the PBR
next-hop via the voice provider. The table 100 shows the
route is in the PBR table.
The dual-stack PBR pattern
A dual-stack subnet has both IPv4 and IPv6 addresses. The operator typically wants both address families to take the same provider path. The dual-stack PBR pattern configures both IPv4 and IPv6 route-maps bound to the same interface:
configure
set policy prefix-list PL-VOICE-SRC rule 10 action permit
set policy prefix-list PL-VOICE-SRC rule 10 prefix '10.10.0.0/24'
set policy prefix-list6 PL-VOICE-SRC-V6 rule 10 action permit
set policy prefix-list6 PL-VOICE-SRC-V6 rule 10 prefix '2001:db8:10::/48'
set policy route-map RM-VOICE-OUT rule 10 action permit
set policy route-map RM-VOICE-OUT rule 10 match ip source address prefix-list PL-VOICE-SRC
set policy route-map RM-VOICE-OUT rule 10 set ip next-hop '198.51.100.1'
set policy route-map RM-VOICE-OUT-V6 rule 10 action permit
set policy route-map RM-VOICE-OUT-V6 rule 10 match ipv6 source address prefix-list6 PL-VOICE-SRC-V6
set policy route-map RM-VOICE-OUT-V6 rule 10 set ipv6 next-hop '2001:db8:ffff::1'
set interfaces ethernet eth1 policy route-map RM-VOICE-OUT
set interfaces ethernet eth1 policy route-map6 RM-VOICE-OUT-V6
commit
save
Two route-maps (one IPv4, one IPv6), two interface bindings (one for each address family), two PBR tables. After commit, IPv4 traffic from 10.10.0.0/24 uses the IPv4 voice provider; IPv6 traffic from 2001:db8:10::/48 uses the IPv6 voice provider.
The dual-stack pattern has a subtle operational requirement: the two providers must have both IPv4 and IPv6 reachability, and the IPv4 next-hop and the IPv6 next-hop must be reachable from the router via the appropriate egress interface. If the upstream provider has only IPv4, the IPv6 PBR will fail because the IPv6 next-hop is unreachable.
Link-local next-hop — a sharp IPv6 edge case
IPv6 allows link-local addresses (fe80::/10) as next-hops.
The router must use NDP to resolve the link-local next-hop to a
MAC address. The link-local next-hop is interpreted in the
context of the egress interface — fe80::1 on eth0 is a
different router from fe80::1 on eth2.
set policy route-map RM-V6-LINK-LOCAL rule 10 action permit
set policy route-map RM-V6-LINK-LOCAL rule 10 match ipv6 source address prefix-list6 PL-V6
set policy route-map RM-V6-LINK-LOCAL rule 10 set ipv6 next-hop 'fe80::1'
set interfaces ethernet eth2 policy route-map6 RM-V6-LINK-LOCAL
The fe80::1 next-hop is ambiguous unless the operator
specifies the egress interface. The VyOS configuration allows
the operator to specify the interface along with the next-hop:
set policy route-map RM-V6-LINK-LOCAL rule 10 set ipv6 next-hop 'fe80::1'
set interfaces ethernet eth2 ipv6 address '2001:db8:beef::1/64'
When the route-map sets a link-local next-hop, FRR uses the egress interface of the route in the table to disambiguate. If the table has only one egress interface (because the route-map generated a single route), the link-local is unambiguous. If the table has multiple egress interfaces (because of ECMP), the link-local is ambiguous and FRR may reject the configuration.
How the configuration is validated
The validation command set for IPv6 PBR:
show policy route-map
show policy prefix-list6
show configuration commands | match 'policy route-map6'
ip -6 rule show
ip -6 route show table all
ip -6 route get <src> <dst>
ip -6 neighbor show
ping6 <ipv6-next-hop>%<egress-ifname>
The first three commands show the configuration. The next three show the kernel view. The last two confirm the next-hop is reachable. A working IPv6 PBR has:
- The IPv6 route-map in
show policy route-mapwithmatch ipv6 source addressandset ipv6 next-hopclauses. - The
policy route-map6binding inshow configuration commands. - The
ip -6 rule showcontains the PBR rule at the expected priority. - The IPv6 PBR table is populated with
ip -6 route show table <id>. - The
ip -6 route getfrom the matching source returns the IPv6 PBR next-hop. ping6 <next-hop>%<egress-ifname>succeeds (NDP resolves).
How it fails
The production failure modes the engineer must recognise:
- IPv4 binding only. The operator binds only
policy route-mapand notpolicy route-map6. IPv6 traffic is not PBR-routed.ip -6 rule showhas no PBR rule. - Wrong prefix-list type. The operator uses
policy prefix-listfor an IPv6 prefix. The route-map does not match IPv6 traffic;match ipv6 source address prefix-listfails to find the prefix-list. - Link-local next-hop unreachable. The IPv6 next-hop is a link-local address that has not been resolved via NDP. The packets are dropped with “neighbour unreachable” errors.
- Dual-stack asymmetry. The IPv4 PBR uses provider-A but the IPv6 PBR uses provider-B. A dual-stack host uses provider-A for IPv4 and provider-B for IPv6. The return path is asymmetric.
- Missing interface binding for IPv6. The route-map is
configured with
match ipv6andset ipv6 next-hop, but the interface binding usespolicy route-mapinstead ofpolicy route-map6. The IPv6 PBR rule is not installed.
Rollback
The recovery from a bad IPv6 PBR configuration:
- Wrong binding:
delete interfaces ethernet <ifname> policy route-map6 <name>; set interfaces ethernet <correct-ifname> policy route-map6 <name>; commit; save. - Wrong route-map:
delete interfaces ethernet <ifname> policy route-map6 <name>; set interfaces ethernet <ifname> policy route-map6 <correct>; commit; save. - Wrong next-hop:
set policy route-map <name> rule <n> set ipv6 next-hop <correct>; commit; save. - Whole-tree rollback:
rollback N; commit; save.
Production discipline
Cross-course references
The VyOS lessons vyos-xi-02-ipv6-addressing and
vyos-xi-05-ipv6-routing cover the IPv6 foundation this lesson
assumes. The lessons vyos-xiii-01-pbr-concept,
vyos-xiii-02-route-maps, and vyos-xiii-03-pbr-rules cover
the PBR foundation. The lesson vyos-xiii-05-pbr-troubleshoot
covers the IPv6-specific operational evidence when a PBR rule
does not fire.
Quiz
Knowledge check · 4 questions
Q1. What is the correct interface binding syntax to apply an IPv6 route-map to eth1 in VyOS 1.5 LTS?
Q2. When a router has only an IPv4 route-map bound via `set interfaces ethernet <ifname> policy route-map`, IPv6 traffic on that interface is PBR-routed by the same rule.
Q3. An operator configures an IPv6 PBR for the voice subnet. The route-map matches `2001:db8:10::/48` and sets the next-hop to `2001:db8:ffff::1`. `ip -6 rule show` shows no PBR rule. The IPv6 voice traffic uses the default route. What is the most likely cause?
The route-map is configured with IPv6 match and set clauses, but the operator forgot to bind the route-map to the interface via `set interfaces ethernet <ifname> policy route-map6 <name>`. Without the binding, FRR has no IPv6 rule to install; `ip -6 rule show` does not contain the PBR rule.
Q4. An operator configures an IPv6 PBR with a link-local next-hop `fe80::1`. The IPv6 rule is installed. `ip -6 route get` returns the next-hop, but packets are dropped with 'neighbour unreachable' errors. What is the most likely cause?
The IPv6 next-hop is a link-local address (`fe80::/10`). The kernel uses NDP to resolve the link-local to a MAC address. The NDP resolution has not completed — either the neighbour is not on the link, the NDP solicitation was dropped by a firewall, or the egress interface is wrong. The route is installed but unusable.
Passing score: 75%. Answers are checked in this browser.