Skip to main content
RunBook Academy

VyOSXIII · Policy-Based RoutingPolicy-based routing

PBR for IPv6 — IPv6 source/destination matches, IPv6 next-hop, IPv6 interface

Advanced⏱ ~18 minset policy route-mapset policy prefix-list6set interfaces ethernet policy route-map6show policy route-mapshow policy prefix-list6ip -6 rule showip -6 route show table allip -6 route getvyosvtysh

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

Not yet marked complete on this device.

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.

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-map with match ipv6 source address and set ipv6 next-hop clauses.
  • The policy route-map6 binding in show configuration commands.
  • The ip -6 rule show contains the PBR rule at the expected priority.
  • The IPv6 PBR table is populated with ip -6 route show table <id>.
  • The ip -6 route get from 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-map and not policy route-map6. IPv6 traffic is not PBR-routed. ip -6 rule show has no PBR rule.
  • Wrong prefix-list type. The operator uses policy prefix-list for an IPv6 prefix. The route-map does not match IPv6 traffic; match ipv6 source address prefix-list fails 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 ipv6 and set ipv6 next-hop, but the interface binding uses policy route-map instead of policy 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

  1. Q1. What is the correct interface binding syntax to apply an IPv6 route-map to eth1 in VyOS 1.5 LTS?

  2. 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.

  3. 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.

  4. 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.