{"article":{"slug":"rfc8950-announce-ipv4-with-an-ipv6-next-hop","title":"RFC8950: Announce IPv4 with an IPv6 next-hop","subtitle":null,"summary":"For the last few days I have been playing with RFC8950 setup, which allows routing of IPv4 on top of IPv6. While logically it’s quite simple, it has a very powerful application towards making “IPv4 an optional” feature riding on top of an IPv6 network (but without any tunnels!)","content_type":"tutorial","language":"en","canonical_url":"https://anuragbhatia.com/post/2026/06/rfc8950-announce-ipv4-with-ipv6-next-hop/","author":{"name":"Anurag Bhatia","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Anurag Bhatia","url":"https://anuragbhatia.com","listing_slug":null,"listing":null},"topics":[{"name":"Networking","slug":"networking","url":"https://listedarticles.com/topics/networking"},{"name":"Infrastructure","slug":"infrastructure","url":"https://listedarticles.com/topics/infrastructure"},{"name":"Tutorials","slug":"tutorials","url":"https://listedarticles.com/topics/tutorials"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":1159,"reading_minutes":5,"published_at":"2026-06-22T00:00:00.000Z","added_at":"2026-10-16T14:22:13.345Z","updated_at":"2026-10-16T14:22:13.345Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/rfc8950-announce-ipv4-with-an-ipv6-next-hop","markdown_url":"https://listedarticles.com/articles/rfc8950-announce-ipv4-with-an-ipv6-next-hop.md","example":false,"citation":"Anurag Bhatia, Anurag Bhatia. \"RFC8950: Announce IPv4 with an IPv6 next-hop.\" 22 Jun 2026. https://anuragbhatia.com/post/2026/06/rfc8950-announce-ipv4-with-ipv6-next-hop/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://anuragbhatia.com/post/2026/06/rfc8950-announce-ipv4-with-ipv6-next-hop/"},"body_markdown":"# RFC8950: Announce IPv4 with an IPv6 next-hop\n\nFor the last few days I have been playing with RFC8950 setup, which allows routing of IPv4 on top of IPv6. While logically it’s quite simple, it has a very powerful application towards making “**IPv4 an optional**” feature riding on top of an IPv6 network (**but without any tunnels!**)\n\nSome of the interesting use cases:\n\n1. A large network can run IPv6 only everywhere on its core and leave IPv4 only on edge devices. This can work without customers doing any tweaking at their end. They still do things the old way but Backbone can run IPv6 only at its core.\n2. An IP transit backbone can run IPv6 only while exchanging IPv4 routes with its customers/peers/upstream over IPv6 sessions. So IPv4 as a “feature” stays but the network in itself is IPv6 only without the overhead of IPv4 interface config, BGP session config, firewall config, etc.\n3. An IXP can offer services without IPv4 essentually by using a (unique) IPv6 at the IX LAN & running route server to exchange both IPv4 & IPv6 routes over the IPv6 only session.\n\nThus what 464XLAT did to the mobile networks - this has the potential to do that for the backbone networks.\n\n### How does it work?\n\nMulti-protocol BGP (MP-BGP) supports announcement of IPv4 routes over IPv6 sessions with IPv4 next-hops and IPv6 routes over IPv4 sessions with IPv6 next-hops. RFC8950 extends this feature for IPv4 to have IPv6 next-hops. So for IPv4 address, next hop is IPv6, IPv6 reach works via usual NDP and IPv4 rides on ethernet frames to the same MAC as discovered by the NDP. Technically RFC8950 only impacts control plane decisions by using IPv6 as the control plane but keeps the data plane as it is. IPv4 stays IPv4 & goes as IPv4 over the wire unlike say some tunnel or 464xLAT etc.\n\n### Hardware support\n\nAs of now it’s quite widely supported by a lot of routing platforms like Juniper JunOS, Cisco IOS XR, Nokia SR OS, Mikrotik, Huawei, BIRD, FRR etc. So, it is very likely supported if you are running a recent version of the OS.\n\n### Demo lab\n\nHere’s a fun lab with two customer routers: C1 & C2 connected via provider routers R1-R2-R3 in Container Lab. All routers here are running open source FRR.\n\n- C1 is IPv6 only on the WAN side facing R1. It originates 10.0.0.0/24 to R1 over an IPv6 session.\n- R1 & R2 are IPv6 only with no IPv4 anywhere on their interfaces (but carry IPv4 routes in their table)\n- R3 has IPv6 with R2 but just IPv4 only with C2. So C2 is like a typical enterprise user who lacks IPv6 deployment and still wants IPv4 only to work.\n- R3 has 100.64.0.0/24 and originates it in the IPv4 table (to IPv6 adjacency - R2)\n- C2 sits on 100.64.0.2/30 given by R3 and communicate in IPv4 only.\n- C1 and C2 can reach each other over this network with parts being IPv6 only without any tunnel.\n\n**topology.yml**\n\n```\nname: rfc8950\ntopology:\n nodes:\n R1:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/R1.conf:/etc/frr/frr.conf            \n R2:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/R2.conf:/etc/frr/frr.conf     \n R3:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/R3.conf:/etc/frr/frr.conf                     \n C1:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/C1.conf:/etc/frr/frr.conf         \n C2:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/C2.conf:/etc/frr/frr.conf               \n links:\n - endpoints: [\"C1:eth1\", \"R1:eth1\"]\n - endpoints: [\"R1:eth2\", \"R2:eth1\"]    \n - endpoints: [\"R2:eth2\", \"R3:eth1\"]  \n - endpoints: [\"R3:eth2\", \"C2:eth1\"]      \n```\n```\n> clab deploy -t topology.yml\n16:37:08 INFO Containerlab started version=0.76.1\n16:37:08 INFO Parsing & checking topology file=topology.yml\n16:37:09 INFO Creating lab directory path=~/ipv4-over-ipv6/clab-rfc8950\n16:37:09 INFO Creating container name=C2\n16:37:09 INFO Creating container name=C1\n16:37:09 INFO Creating container name=R1\n16:37:09 INFO Creating container name=R2\n16:37:09 INFO Creating container name=R3\n16:37:09 INFO Created link: R3:eth2 ▪┄┄▪ C2:eth1\n16:37:09 INFO Created link: C1:eth1 ▪┄┄▪ R1:eth1\n16:37:09 INFO Created link: R1:eth2 ▪┄┄▪ R2:eth1\n16:37:09 INFO Created link: R2:eth2 ▪┄┄▪ R3:eth1\n16:37:09 INFO Adding host entries path=/etc/hosts\n16:37:09 INFO Adding SSH config for nodes path=/etc/ssh/ssh_config.d/clab-rfc8950.conf\n╭─────────────────┬───────────────┬─────────┬───────────────────╮\n│       Name      │   Kind/Image  │  State  │   IPv4/6 Address  │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-C1 │ linux         │ running │ 172.20.20.6       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::6 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-C2 │ linux         │ running │ 172.20.20.4       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::4 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-R1 │ linux         │ running │ 172.20.20.2       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::2 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-R2 │ linux         │ running │ 172.20.20.8       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::8 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-R3 │ linux         │ running │ 172.20.20.5       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::5 │\n╰─────────────────┴───────────────┴─────────┴───────────────────╯\n```\n**Checking C1 for route to C2**\n\n```\nC1# show ip bgp 100.64.0.2\nBGP routing table entry for 100.64.0.0/24, version 2\nPaths: (1 available, best #1, table default)\n Advertised to non peer-group peers:\n 2001:db8:0:1::1\n 65501 65502 65503\n 2001:db8:0:1::1 from 2001:db8:0:1::1 (172.20.20.2)\n (fe80::a8c1:abff:fe60:5467) (used)\n Origin IGP, valid, external, best (First path received)\n Last update: Mon Jun 22 18:57:38 2026\nC1# \n```\n**C1 -> C2 trace**\n\n```\nC1# traceroute 100.64.0.2\ntraceroute to 100.64.0.2 (100.64.0.2), 30 hops max, 46 byte packets\n 1  clab-rfc8950-R1.clab (172.20.20.2)  0.004 ms  0.004 ms  0.002 ms\n 2  clab-rfc8950-R2.clab (172.20.20.8)  0.002 ms  0.003 ms  0.003 ms\n 3  clab-rfc8950-R3.clab (172.20.20.5)  0.002 ms  0.003 ms  0.003 ms\n 4  100.64.0.2 (100.64.0.2)  0.002 ms  0.006 ms  0.003 ms\nC1# \n```\nNote: It took IPv4 from the eth0 management interfaces as deployed by Container Lab for TTL exceeded used in the trace.\n\n**If I check R1, it has only IPv6 sessions but no IPv6 prefixes**\n\n```\nR1# sh bgp ipv6 summary \nIPv6 Unicast Summary (VRF default):\nBGP router identifier 172.20.20.2, local AS number 65501 vrf-id 0\nBGP table version 0\nRIB entries 0, using 0 bytes of memory\nPeers 2, using 1434 KiB of memory\nNeighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc\n2001:db8:0:1::2 4      64512       151       141        0    0    0 00:39:19            0        0 N/A\n2001:db8:0:2::2 4      65502        65        64        0    0    0 00:36:46            0        0 N/A\nTotal number of neighbors 2\nR1# \n```\n**Checking for IPv4 routes on R1**\n\n```\nR1# sh bgp ipv4 \nBGP table version is 4, local router ID is 172.20.20.2, vrf id 0\nDefault local pref 100, local AS 65501\nStatus codes:  s suppressed, d damped, h history, * valid, > best, = multipath,\n i internal, r RIB-failure, S Stale, R Removed\nNexthop codes: @NNN nexthop's vrf id, < announce-nh-self\nOrigin codes:  i - IGP, e - EGP, ? - incomplete\nRPKI validation codes: V valid, I invalid, N Not found\n Network          Next Hop            Metric LocPrf Weight Path\n*> 10.0.0.0/24      fe80::a8c1:abff:fe44:afb8\n 0             0 64512 i\n*> 100.64.0.0/24    fe80::a8c1:abff:fed8:5eb5\n 0 65502 65503 i\nDisplayed  2 routes and 2 total paths\nR1# \n```\n### Router Configs\n\n| Router | Link | \n|---|---|\n| R1 | Click here | \n| R2 | Click here | \n| R3 | Click here | \n| C1 | Click here | \n| C2 | Click here |","body_html":"<h1 id=\"rfc8950-announce-ipv4-with-an-ipv6-next-hop\">RFC8950: Announce IPv4 with an IPv6 next-hop</h1>\n<p>For the last few days I have been playing with RFC8950 setup, which allows routing of IPv4 on top of IPv6. While logically it’s quite simple, it has a very powerful application towards making “<strong>IPv4 an optional</strong>” feature riding on top of an IPv6 network (<strong>but without any tunnels!</strong>)</p>\n<p>Some of the interesting use cases:</p>\n<ol><li>A large network can run IPv6 only everywhere on its core and leave IPv4 only on edge devices. This can work without customers doing any tweaking at their end. They still do things the old way but Backbone can run IPv6 only at its core.</li><li>An IP transit backbone can run IPv6 only while exchanging IPv4 routes with its customers/peers/upstream over IPv6 sessions. So IPv4 as a “feature” stays but the network in itself is IPv6 only without the overhead of IPv4 interface config, BGP session config, firewall config, etc.</li><li>An IXP can offer services without IPv4 essentually by using a (unique) IPv6 at the IX LAN &amp; running route server to exchange both IPv4 &amp; IPv6 routes over the IPv6 only session.</li></ol>\n<p>Thus what 464XLAT did to the mobile networks - this has the potential to do that for the backbone networks.</p>\n<h3 id=\"how-does-it-work\">How does it work?</h3>\n<p>Multi-protocol BGP (MP-BGP) supports announcement of IPv4 routes over IPv6 sessions with IPv4 next-hops and IPv6 routes over IPv4 sessions with IPv6 next-hops. RFC8950 extends this feature for IPv4 to have IPv6 next-hops. So for IPv4 address, next hop is IPv6, IPv6 reach works via usual NDP and IPv4 rides on ethernet frames to the same MAC as discovered by the NDP. Technically RFC8950 only impacts control plane decisions by using IPv6 as the control plane but keeps the data plane as it is. IPv4 stays IPv4 &amp; goes as IPv4 over the wire unlike say some tunnel or 464xLAT etc.</p>\n<h3 id=\"hardware-support\">Hardware support</h3>\n<p>As of now it’s quite widely supported by a lot of routing platforms like Juniper JunOS, Cisco IOS XR, Nokia SR OS, Mikrotik, Huawei, BIRD, FRR etc. So, it is very likely supported if you are running a recent version of the OS.</p>\n<h3 id=\"demo-lab\">Demo lab</h3>\n<p>Here’s a fun lab with two customer routers: C1 &amp; C2 connected via provider routers R1-R2-R3 in Container Lab. All routers here are running open source FRR.</p>\n<ul><li>C1 is IPv6 only on the WAN side facing R1. It originates 10.0.0.0/24 to R1 over an IPv6 session.</li><li>R1 &amp; R2 are IPv6 only with no IPv4 anywhere on their interfaces (but carry IPv4 routes in their table)</li><li>R3 has IPv6 with R2 but just IPv4 only with C2. So C2 is like a typical enterprise user who lacks IPv6 deployment and still wants IPv4 only to work.</li><li>R3 has 100.64.0.0/24 and originates it in the IPv4 table (to IPv6 adjacency - R2)</li><li>C2 sits on 100.64.0.2/30 given by R3 and communicate in IPv4 only.</li><li>C1 and C2 can reach each other over this network with parts being IPv6 only without any tunnel.</li></ul>\n<p><strong>topology.yml</strong></p>\n<pre><code>name: rfc8950\ntopology:\n nodes:\n R1:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/R1.conf:/etc/frr/frr.conf            \n R2:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/R2.conf:/etc/frr/frr.conf     \n R3:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/R3.conf:/etc/frr/frr.conf                     \n C1:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/C1.conf:/etc/frr/frr.conf         \n C2:\n kind: linux\n image: frr-with-bgpd\n binds:\n - configs/C2.conf:/etc/frr/frr.conf               \n links:\n - endpoints: [&quot;C1:eth1&quot;, &quot;R1:eth1&quot;]\n - endpoints: [&quot;R1:eth2&quot;, &quot;R2:eth1&quot;]    \n - endpoints: [&quot;R2:eth2&quot;, &quot;R3:eth1&quot;]  \n - endpoints: [&quot;R3:eth2&quot;, &quot;C2:eth1&quot;]      </code></pre>\n<pre><code>&gt; clab deploy -t topology.yml\n16:37:08 INFO Containerlab started version=0.76.1\n16:37:08 INFO Parsing &amp; checking topology file=topology.yml\n16:37:09 INFO Creating lab directory path=~/ipv4-over-ipv6/clab-rfc8950\n16:37:09 INFO Creating container name=C2\n16:37:09 INFO Creating container name=C1\n16:37:09 INFO Creating container name=R1\n16:37:09 INFO Creating container name=R2\n16:37:09 INFO Creating container name=R3\n16:37:09 INFO Created link: R3:eth2 ▪┄┄▪ C2:eth1\n16:37:09 INFO Created link: C1:eth1 ▪┄┄▪ R1:eth1\n16:37:09 INFO Created link: R1:eth2 ▪┄┄▪ R2:eth1\n16:37:09 INFO Created link: R2:eth2 ▪┄┄▪ R3:eth1\n16:37:09 INFO Adding host entries path=/etc/hosts\n16:37:09 INFO Adding SSH config for nodes path=/etc/ssh/ssh_config.d/clab-rfc8950.conf\n╭─────────────────┬───────────────┬─────────┬───────────────────╮\n│       Name      │   Kind/Image  │  State  │   IPv4/6 Address  │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-C1 │ linux         │ running │ 172.20.20.6       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::6 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-C2 │ linux         │ running │ 172.20.20.4       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::4 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-R1 │ linux         │ running │ 172.20.20.2       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::2 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-R2 │ linux         │ running │ 172.20.20.8       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::8 │\n├─────────────────┼───────────────┼─────────┼───────────────────┤\n│ clab-rfc8950-R3 │ linux         │ running │ 172.20.20.5       │\n│                 │ frr-with-bgpd │         │ 3fff:172:20:20::5 │\n╰─────────────────┴───────────────┴─────────┴───────────────────╯</code></pre>\n<p><strong>Checking C1 for route to C2</strong></p>\n<pre><code>C1# show ip bgp 100.64.0.2\nBGP routing table entry for 100.64.0.0/24, version 2\nPaths: (1 available, best #1, table default)\n Advertised to non peer-group peers:\n 2001:db8:0:1::1\n 65501 65502 65503\n 2001:db8:0:1::1 from 2001:db8:0:1::1 (172.20.20.2)\n (fe80::a8c1:abff:fe60:5467) (used)\n Origin IGP, valid, external, best (First path received)\n Last update: Mon Jun 22 18:57:38 2026\nC1# </code></pre>\n<p><strong>C1 -&gt; C2 trace</strong></p>\n<pre><code>C1# traceroute 100.64.0.2\ntraceroute to 100.64.0.2 (100.64.0.2), 30 hops max, 46 byte packets\n 1  clab-rfc8950-R1.clab (172.20.20.2)  0.004 ms  0.004 ms  0.002 ms\n 2  clab-rfc8950-R2.clab (172.20.20.8)  0.002 ms  0.003 ms  0.003 ms\n 3  clab-rfc8950-R3.clab (172.20.20.5)  0.002 ms  0.003 ms  0.003 ms\n 4  100.64.0.2 (100.64.0.2)  0.002 ms  0.006 ms  0.003 ms\nC1# </code></pre>\n<p>Note: It took IPv4 from the eth0 management interfaces as deployed by Container Lab for TTL exceeded used in the trace.</p>\n<p><strong>If I check R1, it has only IPv6 sessions but no IPv6 prefixes</strong></p>\n<pre><code>R1# sh bgp ipv6 summary \nIPv6 Unicast Summary (VRF default):\nBGP router identifier 172.20.20.2, local AS number 65501 vrf-id 0\nBGP table version 0\nRIB entries 0, using 0 bytes of memory\nPeers 2, using 1434 KiB of memory\nNeighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc\n2001:db8:0:1::2 4      64512       151       141        0    0    0 00:39:19            0        0 N/A\n2001:db8:0:2::2 4      65502        65        64        0    0    0 00:36:46            0        0 N/A\nTotal number of neighbors 2\nR1# </code></pre>\n<p><strong>Checking for IPv4 routes on R1</strong></p>\n<pre><code>R1# sh bgp ipv4 \nBGP table version is 4, local router ID is 172.20.20.2, vrf id 0\nDefault local pref 100, local AS 65501\nStatus codes:  s suppressed, d damped, h history, * valid, &gt; best, = multipath,\n i internal, r RIB-failure, S Stale, R Removed\nNexthop codes: @NNN nexthop&#39;s vrf id, &lt; announce-nh-self\nOrigin codes:  i - IGP, e - EGP, ? - incomplete\nRPKI validation codes: V valid, I invalid, N Not found\n Network          Next Hop            Metric LocPrf Weight Path\n*&gt; 10.0.0.0/24      fe80::a8c1:abff:fe44:afb8\n 0             0 64512 i\n*&gt; 100.64.0.0/24    fe80::a8c1:abff:fed8:5eb5\n 0 65502 65503 i\nDisplayed  2 routes and 2 total paths\nR1# </code></pre>\n<h3 id=\"router-configs\">Router Configs</h3>\n<div class=\"table-wrap\"><table><thead><tr><th>Router</th><th>Link</th></tr></thead><tbody><tr><td>R1</td><td>Click here</td></tr><tr><td>R2</td><td>Click here</td></tr><tr><td>R3</td><td>Click here</td></tr><tr><td>C1</td><td>Click here</td></tr><tr><td>C2</td><td>Click here</td></tr></tbody></table></div>","headings":[{"level":1,"text":"RFC8950: Announce IPv4 with an IPv6 next-hop","id":"rfc8950-announce-ipv4-with-an-ipv6-next-hop"},{"level":3,"text":"How does it work?","id":"how-does-it-work"},{"level":3,"text":"Hardware support","id":"hardware-support"},{"level":3,"text":"Demo lab","id":"demo-lab"},{"level":3,"text":"Router Configs","id":"router-configs"}]}}