Summary: This article describes how to enable IPv6 prefix exchange across Versa paired TVIs using a single MP-BGP session over IPv4 transport with IPv4-mapped IPv6 addressing (::ffff:169.254.0.X/127) on the TVI interface. This approach enables dual-stack local internet breakout — exchanging both IPv4 and IPv6 prefixes between VRs on the same CPE — using one BGP session and no additional address allocation.
Versa SD-WAN CPEs commonly host multiple Virtual Routing Instances (VRs) on the same appliance — for example, a WAN transport VR (Broadband-Transport-VR) and a LAN breakout VR (Meta-LAN-VR). These VRs are isolated from each other by design. To allow them to exchange routes — so that LAN-side prefixes are known to the WAN VR and the WAN default route is known to the LAN VR — Versa uses Paired Tunnel Virtual Interfaces (TVIs).
A paired TVI is a back-to-back point-to-point link between two VRs on the same appliance. BGP runs across this link to exchange prefixes between the two VRs. The data-plane traffic that is steered by those routes also traverses the paired TVI.
For IPv4, paired TVIs have always used RFC 3927 link-local addressing (169.254.0.0/16) for the BGP peering endpoints. This range is ideal because:
For IPv6, the natural equivalent is link-local addresses (fe80::/10). However, the current VOS provisioning model has a schema limitation that prevents IPv6 link-local BGP peering across paired TVIs from committing successfully (see Section 2). This article documents the validated workaround: MP-BGP over IPv4 with IPv4-mapped IPv6 next-hops.
Attempting to configure an IPv6 link-local BGP neighbor (fe80::X) across a paired TVI fails at commit time with the following diagnostic:
Aborted: Commit failed due to inconsistent configuration.
Diagnostic string: bgpPeerEntry{75004
enum<2> fe800000000000000169025400000003 0
enum<2> fe800000000000000169025400000002 0 0}
/bgpPeerLocalAddrScopeId
Root cause: The BGP4V2-MIB consistency check requires that any link-local address in a bgpPeerEntry row carry a non-zero bgpPeerLocalAddrScopeId (the interface ifIndex that scopes the link-local address). The current bgp neighbor schema exposes only a local-address leaf, which does not propagate a scope ID to the MIB-row builder. As a result, the commit-time validator rejects every fe80:: BGP neighbor with scope-id 0, regardless of how the local-address is specified.
Instead of running a separate IPv6 BGP session (which the platform cannot commit), run a single BGP session over IPv4 and enable both address families on it. This is standard MP-BGP (RFC 4760). IPv6 prefixes are carried in MP_REACH_NLRI / MP_UNREACH_NLRI path attributes inside the same UPDATE messages as IPv4 prefixes.
For the MP-BGP session to carry IPv6 NLRI, the BGP daemon needs an IPv6 next-hop to encode in the UPDATE. This is provided by configuring an IPv4-mapped IPv6 address (::ffff:169.254.0.X/127) on the TVI interface alongside the existing IPv4 /31. The daemon selects this address as the IPv6 next-hop for advertised IPv6 prefixes. Received routes install in the IPv6 RIB with ::ffff:X as the next-hop, which the FIB resolves through the underlying IPv4 forwarding path across the paired TVI.
IPv4-mapped IPv6 addresses (::ffff:X) are not on-wire routable IPv6 addresses. They encode an IPv4 address in the low 32 bits of a 128-bit field. In this context they serve two roles:
Because ::ffff:169.254.0.X embeds an IPv4 link-local address (169.254.0.X), it inherits the non-routable property of the 169.254.0.0/16 range. Even if a misconfigured redistribution policy were to leak this prefix into external BGP, no external peer would install a route toward it. No filter is required to prevent leakage.
|
Key benefit vs. ULA workaround: Unlike a ULA /127 workaround, this approach requires no address allocation, no redistribution policy split (v4 and v6 can share the same policy), no explicit leak-prevention filter term, and no additional BGP session. One IPv4 session carries both address families. |
The example below uses a standard paired-TVI between Broadband-Transport-VR (WAN-facing) and Meta-LAN-VR (LAN-facing). The IPv4 /31 addressing follows the standard 169.254.0.X convention. The IPv4-mapped IPv6 address is added to the same TVI unit on both sides.
Broadband-Transport-VR Meta-LAN-VR
tvi-0/602.0 tvi-0/603.0
169.254.0.2/31 ←──────────→ 169.254.0.3/31
::ffff:169.254.0.2/127 ::ffff:169.254.0.3/127
BGP AS 64513 BGP AS 64514
neighbor 169.254.0.3 neighbor 169.254.0.2
family inet + inet6 family inet + inet6
Add the IPv4-mapped IPv6 address to the inet6 family on both TVI units alongside the existing IPv4 /31:
interfaces {
tvi-0/602 {
unit 0 {
family {
inet { address 169.254.0.2/31; }
inet6 { address ::ffff:169.254.0.2/127; } /* IPv4-mapped, WAN side */
}
}
}
tvi-0/603 {
unit 0 {
family {
inet { address 169.254.0.3/31; }
inet6 { address ::ffff:169.254.0.3/127; } /* IPv4-mapped, LAN side */
}
}
}
}
Enable both inet and inet6 unicast families on the existing IPv4 BGP group. No additional IPv6 neighbor entry is required.
routing-instances Broadband-Transport-VR {
policy-options {
redistribute-to-bgp ST-Policy;
redistribute-to-bgp6 ST-Policy; /* same policy — no split needed */
}
protocols {
bgp {
3000 {
router-id 169.254.0.1;
local-as { as-number 64513; }
group ST_Group {
type external;
family {
inet { unicast { prefix-limit-control { action drop; } } }
inet6 { unicast { prefix-limit-control { action drop; } } }
}
enable-alarms false;
neighbor 169.254.0.3 {
local-address 169.254.0.2;
peer-as 64514;
enable-alarms false;
}
}
}
}
}
}
routing-instances Meta-LAN-VR {
policy-options {
redistribute-to-bgp Default-Policy-To-BGP;
redistribute-to-bgp6 Default-Policy-To-BGP6;
}
protocols {
bgp {
3054 {
router-id 169.254.0.42;
local-as { as-number 64514; }
group ST-Group-1 {
type external;
peer-as 64513;
enable-alarms false;
local-address 169.254.0.3;
family {
inet { unicast { prefix-limit-control { action drop; } } }
inet6 { unicast { prefix-limit-control { action drop; } } }
}
neighbor 169.254.0.2;
import From_ST_Broadband;
export To_ST_DIA;
}
}
}
}
}
Confirm both v4 and the mapped v6 address are present on each TVI. No fe80:: or ::ffff: address should be absent:
admin@DUT-cli> show interfaces brief | tab
NAME OPER VRF IP
-----------------------------------------------------
tvi-0/602.0 up Broadband-Transport-VR 169.254.0.2/31
::ffff:169.254.0.2/127
tvi-0/603.0 up Meta-LAN-VR 169.254.0.3/31
::ffff:169.254.0.3/127
Verify the IPv4 BGP sessions are Established on both VRs. There is no separate IPv6 neighbor row — both AFs run over the single IPv4 session:
admin@DUT-cli> show bgp neighbor brief
routing-instance: Broadband-Transport-VR
Neighbor V MsgRcvd MsgSent Uptime State/PfxRcd PfxSent AS
169.254.0.3 4 1773 4902 02:46:52 3 2 64514
routing-instance: Meta-LAN-VR
Neighbor V MsgRcvd MsgSent Uptime State/PfxRcd PfxSent AS
169.254.0.2 4 2447 2432 17:38:12 2 2 64513
169.254.0.4 4 2433 2435 17:38:12 1 2 64513
Check that IPv6 prefixes are being received over the IPv4 session on both sides:
On Meta-LAN-VR — confirm the IPv6 default route is received from Broadband-Transport-VR:
admin@DUT-cli> show route table ipv6.unicast routing-instance Meta-LAN-VR
receive-protocol bgp neighbor-address 169.254.0.2
Routes for Routing instance : Meta-LAN-VR AFI: ipv6 SAFI: unicast
Prefix/Mask Next-hop MED Lclpref AS path
----------- -------- --- ------- -------
::/0 ::ffff:169.254.0.2 0 120 64513
On Broadband-Transport-VR — confirm the LAN prefix is received from Meta-LAN-VR:
admin@DUT-cli> show route table ipv6.unicast routing-instance Broadband-Transport-VR
receive-protocol bgp neighbor-address 169.254.0.3
Routes for Routing instance : Broadband-Transport-VR AFI: ipv6 SAFI: unicast
Prefix/Mask Next-hop MED Lclpref AS path
----------- -------- --- ------- -------
::ffff:169.254.0.2/127 ::ffff:169.254.0.3 0 100 64514
fd00:beef:1::/64 ::ffff:169.254.0.3 0 100 64514
|
Expected output: fd00:beef:1::/64 (the LAN subnet) appears in Broadband-Transport-VR's BGP receive table with next-hop ::ffff:169.254.0.3. The ::/0 default route appears in Meta-LAN-VR's BGP receive table with next-hop ::ffff:169.254.0.2. Both are correct and confirm that the MP-BGP dual-AF session is exchanging IPv6 prefixes across the paired TVI. |
Confirm the full IPv6 route table in Meta-LAN-VR shows active routes for both the default and the LAN prefix:
admin@DUT-cli> show route table ipv6.unicast routing-instance Meta-LAN-VR
::/0
[BGP/0] 00:41:22 Active
> to ::ffff:169.254.0.2 via Indirect Non SDWAN
::ffff:169.254.0.2/127
[conn/0] 00:41:22 Active
> via tvi-0/603.0 Non SDWAN
::ffff:169.254.0.3/128
[local/0] 00:41:23 Active
> direct connected Non SDWAN
fd00:beef:1::/64
[conn/0] 01:00:52 Active
> via vni-0/2.0 Non SDWAN
fd00:beef:1::1/128
[local/0] 01:00:52 Active
> direct connected Non SDWAN
The following describes the end-to-end forwarding path for an IPv6 host on LAN1 accessing the internet:
LAN Host CPE Internet
(fd00:beef:1::abcd)
│ │
│── SRC: fd00:beef:1::abcd ──────────────────────────────────────→│
│ DST: 2001:4860::8888 │
│ │
│ ┌──────── Meta-LAN-VR ────────────────────────┐ │
│ │ FIB lookup: 2001:4860::8888 │ │
│ │ Match: ::/0 → ::ffff:169.254.0.2 │ │
│ │ Resolves: IPv4 fwd → 169.254.0.2 │ │
│ │ Egress: tvi-0/603.0 │ │
│ └─────────────────────────────────────────────┘ │
│ │ (across paired TVI) │
│ ┌──────── Broadband-Transport-VR ─────────────┐ │
│ │ FIB lookup: 2001:4860::8888 │ │
│ │ Match: ::/0 → 2001:db8:cafe:1::1 │ │
│ │ Egress: vni-0/0.0 (WAN) │ │
│ └─────────────────────────────────────────────┘ │
│ ──────────────→│
Return traffic follows the reverse path. Broadband-Transport-VR has the LAN prefix fd00:beef:1::/64 in its IPv6 RIB (received via MP-BGP from Meta-LAN-VR), so return packets are directed back across the paired TVI toward the LAN host.
Apply the following changes to every paired-TVI group in the device template:
For deployments using the standard 169.254.0.X/31 paired-TVI numbering scheme, the IPv4-mapped IPv6 addresses are derived directly:
|
TVI |
IPv4 Address |
IPv4-Mapped IPv6 |
VR |
|
tvi-0/602.0 |
169.254.0.2/31 |
::ffff:169.254.0.2/127 |
Broadband-Transport-VR |
|
tvi-0/603.0 |
169.254.0.3/31 |
::ffff:169.254.0.3/127 |
Meta-LAN-VR |
|
tvi-0/604.0 |
169.254.0.4/31 |
::ffff:169.254.0.4/127 |
MPLS-Transport-VR |
|
tvi-0/605.0 |
169.254.0.5/31 |
::ffff:169.254.0.5/127 |
Meta-LAN-VR |
|
tvi-0/606.0 |
169.254.0.6/31 |
::ffff:169.254.0.6/127 |
a-inet (or equiv.) |
|
tvi-0/607.0 |
169.254.0.7/31 |
::ffff:169.254.0.7/127 |
europa-guest-edge |
|
Aspect |
Link-Local v6 BGP |
ULA /127 + Filter |
MP-BGP over IPv4 (this article) |
|
BGP sessions per TVI pair |
2 (v4 + v6) |
2 (v4 + v6) |
1 (v4 only, both AFs) |
|
VOS commit result |
Fails — bgpPeerLocalAddrScopeId |
Succeeds |
Succeeds |
|
Address allocation needed |
None |
ULA /64 from RFC 4193 /48 |
None — derived from v4 |
|
Leak prevention |
By protocol (fe80 non-routable) |
Explicit reject filter term |
By address property (::ffff: non-routable) |
|
Policy split required |
No |
Yes (v4/v6 separate) |
No (same policy for both) |
|
Standards basis |
RFC 2545, RFC 7404 |
RFC 4193 + RFC 4760 |
RFC 4760 (MP-BGP), RFC 4798-style next-hop |
|
Recommended for VOS |
Pending VOS fix |
Functional workaround |
Recommended — validated in lab |
|
Symptom |
Likely Cause |
Resolution |
|
bgpPeerLocalAddrScopeId on commit |
fe80:: address still configured on TVI inet6 family |
Remove fe80:: addresses from TVI units. Only ::ffff:X/127 and the v4 /31 should remain. |
|
IPv6 family not negotiated (show bgp neighbor shows only inet) |
inet6 unicast not in the BGP group family block |
Add family { inet6 { unicast; } } to the group in the device template and recommit. |
|
IPv6 routes present in BGP table but not installing in FIB |
Missing static ::/0 default on WAN VR, or redistribution policy not configured for v6 |
Confirm static ::/0 with outgoing interface in Broadband-Transport-VR. Confirm redistribute-to-bgp6 in both VRs. |
|
::ffff:X/127 appears in BGP advertisements to external peers |
Redistribution policy matches direct routes without filtering the /127 |
Add a reject term for ::ffff:0:0/96 (or the specific /127) before the direct-accept term in the v6 redistribution policy. |
|
Commit error: policy with v6 clauses cannot be used for v4 |
Same policy name used for both redistribute-to-bgp and redistribute-to-bgp6, but policy contains v6 match clauses |
Split into separate v4 and v6 policies. Assign each to the correct redistribute-to-bgp / redistribute-to-bgp6 stanza. |