################################
Inter-VRF Routing over VRF Lite
################################

**Virtual Routing and Forwarding** is a technology that allow multiple instance
of a routing table to exist within a single device. One of the key aspect of
**VRFs** is that do not share the same routes or interfaces, therefore packets
are forwarded between interfaces that belong to the same VRF only.

Any information related to a VRF is not exchanged between devices -or in the
same device- by default, this is a technique called **VRF-Lite**.

Keep networks isolated is -in general- a good principle, but there are cases
where you might need that some network can access other in a different VRF.

The scope of this document is to cover such cases in a dynamic way without the
use of MPLS-LDP.

General information about L3VPNs can be found in the :ref:`configuration/vrf/index:L3VPN VRFs` chapter.

********
Overview
********

Let’s say we have a requirement to have multiple networks.

* LAN 1
* LAN 2
* Management
* Internet

Both LANs have to be able to route between each other, both will have managed
devices through a dedicated management network and both will need Internet
access yet the LAN2 will need access to some set of outside networks, not all.
The management network will need access to both LANs but cannot have access
to/from the outside.

This scenario could be a nightmare applying regular routing and might need
filtering in multiple interfaces.

A simple solution could be using different routing tables, or VRFs
for all the networks so we can keep the routing restrictions.
But for us to route between the different VRFs we would need a cable or a
logical connection between each other:

* One cable/logical connection between LAN1 and LAN2
* One cable/logical connection between LAN1 and Internet
* One cable/logical connection between LAN2 and Internet
* One cable/logical connection between LAN1 and Management
* One cable/logical connection between LAN2 and Management

As we can see this is unpractical.

To address this scenario we will use to our advantage an extension of the BGP
routing protocol that will help us in the “Export” between VRFs without the
need for MPLS.

MP-BGP or MultiProtocol BGP introduces two main concepts to solve this
limitation:
- Route Distinguisher (RD): Is used to distinguish between different VRFs
–called VPNs- inside the BGP Process. The RD is appended to each IPv4 Network
that is advertised into BGP for that VPN making it a unique VPNv4 route.
- Route Target (RT): This is an extended BGP community append to the VPNv4 route
in the Import/Export process. When a route passes from the VRF routing table
into the BGP process it will add the configured export extended community(ies)
for that VPN. When that route needs to go from BGP into the VRF routing table
will only pass if that given VPN import policy matches any of the appended
community(ies) into that prefix.

********
Topology
********
.. image:: /_static/images/inter-vrf-routing-vrf-lite.png
   :width: 70%
   :align: center
   :alt: Network Topology Diagram




IP Schema
=========

+----------+------------+----------------+------------------+
| Device-A |  Device-B  |  IPv4 Network  |   IPv6 Network   |
+----------+------------+----------------+------------------+
|   Core   |    LAN1    |  10.1.1.0/30   |  2001:db8::/127  |
+----------+------------+----------------+------------------+
|   Core   |    LAN2    | 172.16.2.0/30  |  2001:db8::2/127 |
+----------+------------+----------------+------------------+
|   Core   | Management | 192.168.3.0/30 |  2001:db8::4/127 |
+----------+------------+----------------+------------------+
|   Core   |     ISP    |  10.2.2.0/30   |  2001:db8::6/127 |
+----------+------------+----------------+------------------+

RD & RT Schema
==============

+------------+-----------+-----------+
|    VRF     |     RD    |     RT    |
+------------+-----------+-----------+
|    LAN1    |  64496:1  |  64496:1  |
+------------+-----------+-----------+
|    LAN2    |  64496:2  |  64496:2  |
+------------+-----------+-----------+
| Management | 64496:50  | 64496:50  |
+------------+-----------+-----------+
|  Internet  | 64496:100 | 64496:100 |
+------------+-----------+-----------+

**************
Configurations
**************

.. note:: We use a static route configuration in between the Core and each
   LAN and Management router, and BGP between the Core router and the ISP router
   but any dynamic routing protocol can be used.

Remote Networks
===============

The following template configuration can be used in each remote router based
in our topology.

.. code-block:: none

   # Interface Configuration
   set interface eth eth<N> address <IP ADDRESS/CIDR>

   # Static default route back to Core
   set procotols static route 0.0.0.0/0 next-hop <CORE IP ADDRESS>

Core Router
===========

Step 1: VRF and Configurations to remote networks
-------------------------------------------------

- Configuration



Set the VRF name and Table ID, set interface address and bind it to the VRF.
Last add the static route to the remote network.

.. code-block:: none

   # VRF name and table ID (MANDATORY)
   set vrf name <VRF> table <ID>

   # Interface Configuration
   set interface eth eth<N> address <IP ADDRESS/CIDR>

   # Assign interface to VRF
   set interface eth eth<N> vrf <VRF>

   # Static route to remote Network
   set vrf name <VRF> protocols static route <NETWORK/CIDR> next-hop <REMOTE IP ADDRESS>

- Verification



Checking the routing table of the VRF should reveal both static and connected
entries active. A PING test between the Core and remote router is a way to
validate connectivity within the VRF.

.. code-block:: none

   # show ip route vrf <VRF>
   # show ipv6 route vrf <VRF>

   vyos@Core:~$ show ip route vrf LAN1
   Codes: K - kernel route, C - connected, S - static, R - RIP,
          O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
          T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
          f - OpenFabric,
          > - selected route, * - FIB route, q - queued, r - rejected, b - backup
          t - trapped, o - offload failure

   VRF LAN1:
   S>* 10.0.0.0/24 [1/0] via 10.1.1.2, eth0, weight 1, 00:05:41
   C>* 10.1.1.0/30 is directly connected, eth0, 00:05:44

   vyos@Core:~$ show ipv6 route vrf LAN1
   Codes: K - kernel route, C - connected, S - static, R - RIPng,
          O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table,
          v - VNC, V - VNC-Direct, A - Babel, F - PBR,
          f - OpenFabric,
          > - selected route, * - FIB route, q - queued, r - rejected, b - backup
          t - trapped, o - offload failure

   VRF LAN1:
   C>* 2001:db8::/127 is directly connected, eth0, 00:18:43
   S>* 2001:db8:0:1::/64 [1/0] via 2001:db8::1, eth0, weight 1, 00:16:03
   C>* fe80::/64 is directly connected, eth0, 00:18:43

   # ping <DESTINATION> vrf <VRF>

   vyos@Core:~$ ping 10.1.1.2 vrf LAN1
   PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
   64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=1.52 ms
   64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.830 ms
   ^C
   --- 10.1.1.2 ping statistics ---
   2 packets transmitted, 2 received, 0% packet loss, time 1002ms
   rtt min/avg/max/mdev = 0.830/1.174/1.518/0.344 ms
   vyos@Core:~$ ping 10.0.0.1 vrf LAN1
   PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
   64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.785 ms
   64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.948 ms
   ^C
   --- 10.0.0.1 ping statistics ---
   2 packets transmitted, 2 received, 0% packet loss, time 1002ms
   rtt min/avg/max/mdev = 0.785/0.866/0.948/0.081 ms

   vyos@Core:~$ ping 2001:db8:0:1::1 vrf LAN1
   PING 2001:db8:0:1::1(2001:db8:0:1::1) 56 data bytes
   64 bytes from 2001:db8:0:1::1: icmp_seq=1 ttl=64 time=3.04 ms
   64 bytes from 2001:db8:0:1::1: icmp_seq=2 ttl=64 time=1.04 ms
   64 bytes from 2001:db8:0:1::1: icmp_seq=3 ttl=64 time=0.925 ms
   ^C
   --- 2001:db8:0:1::1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2004ms
   rtt min/avg/max/mdev = 0.925/1.665/3.035/0.969 ms

Step 2: BGP Configuration for VRF-Lite
--------------------------------------


- Configuration



Setting BGP global local-as as well inside the VRF. Redistribute static routes
to inject configured networks into the BGP process but still inside the VRF.


.. code-block:: none

   # set BGP global local-as
   set protocols bgp system-as <ASN>

   # set BGP VRF local-as and redistribution
   set vrf name <VRF> protocols bgp system-as <ASN>
   set vrf name <VRF> protocols bgp address-family <AF IPv4/IPv6> redistribute static

- Verification



Check the BGP VRF table and verify if the static routes are injected showing
the correct next-hop information.

.. code-block:: none

   # show ip bgp vrf <VRF>
   # show bgp vrf <VRF> ipv6

   vyos@Core:~$ show ip bgp vrf LAN1
   BGP table version is 3, local router ID is 10.1.1.1, vrf id 8
   Default local pref 100, local AS 64496
   Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                  i internal, r RIB-failure, S Stale, R Removed
   Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
   Origin codes:  i - IGP, e - EGP, ? - incomplete
   RPKI validation codes: V valid, I invalid, N Not found

      Network          Next Hop            Metric LocPrf Weight Path
   *> 10.0.0.0/24      10.1.1.2                 0         32768 ?

   vyos@Core# run show bgp vrf LAN1 ipv6
   BGP table version is 13, local router ID is 10.1.1.1, vrf id 8
   Default local pref 100, local AS 64496
   Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                  i internal, r RIB-failure, S Stale, R Removed
   Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
   Origin codes:  i - IGP, e - EGP, ? - incomplete
   RPKI validation codes: V valid, I invalid, N Not found

      Network          Next Hop            Metric LocPrf Weight Path
   *> 2001:db8:0:1::/64
                       2001:db8::1              0         32768 ?


Step 3: VPN Configuration
-------------------------


- Configuration


Within the VRF we set the Route-Distinguisher (RD) and Route-Targets (RT), then
we enable the export/import VPN.


.. code-block:: none

   # set Route-distinguisher
   set vrf name <VRF> protocols bgp address-family <AF IPv4/IPv6> rd vpn export '<RD>'

   # set route-target for import/export
   # Note: RT are a list that can be more than one community between apostrophe
   #       and separated by blank space. Ex: '<RT:1> <RT:2> <RT:3>'
   set vrf name <VRF> protocols bgp address-family <AF IPv4/IPv6> route-target vpn export '<RT:Export>'
   set vrf name <VRF> protocols bgp address-family <AF IPv4/IPv6> route-target vpn import '<RT:Import>'

   # Enable VPN export/import under this VRF
   set vrf name <VRF> protocols bgp address-family <AF IPv4/IPv6> export vpn
   set vrf name <VRF> protocols bgp address-family <AF IPv4/IPv6> import vpn

A key point to understand is that if we need two VRFs to communicate between
each other EXPORT rt from VRF1 has to be in the IMPORT rt list from VRF2. But
this is only in ONE direction, to complete the communication the EXPORT rt from
VRF2 has to be in the IMPORT rt list from VRF1.

There are some cases where this is not needed -for example, in some
DDoS appliance- but most inter-vrf routing designs use the above configurations.

- Verification



After configured all the VRFs involved in this topology we take a deeper look
at both BGP and Routing table for the VRF LAN1

.. code-block:: none

   # show ip bgp vrf <VRF>
   # show bgp vrf <VRF> ipv6

   vyos@Core# run show ip bgp vrf LAN1
   BGP table version is 53, local router ID is 10.1.1.1, vrf id 8
   Default local pref 100, local AS 64496
   Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                  i internal, r RIB-failure, S Stale, R Removed
   Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
   Origin codes:  i - IGP, e - EGP, ? - incomplete
   RPKI validation codes: V valid, I invalid, N Not found

      Network          Next Hop            Metric LocPrf Weight Path
   *> 0.0.0.0/0        10.2.2.2@7<                            0 64497 i
   *> 10.0.0.0/24      10.1.1.2                 0         32768 ?
   *> 10.2.2.0/30      10.2.2.2@7<              0             0 64497 ?
   *> 192.0.2.0/24     10.2.2.2@7<              0             0 64497 ?
   *> 192.168.0.0/24   192.168.3.2@11<          0         32768 ?
   *> 198.51.100.0/24  10.2.2.2@7<              0             0 64497 ?
   *> 203.0.113.0/24   10.2.2.2@7<              0             0 64497 ?

   vyos@Core# run show bgp vrf LAN1 ipv6
   BGP table version is 13, local router ID is 10.1.1.1, vrf id 8
   Default local pref 100, local AS 64496
   Status codes:  s suppressed, d damped, h history, * valid, > best, = multipath,
                  i internal, r RIB-failure, S Stale, R Removed
   Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
   Origin codes:  i - IGP, e - EGP, ? - incomplete
   RPKI validation codes: V valid, I invalid, N Not found

   Network          Next Hop            Metric LocPrf Weight Path
   *> ::/0             fe80::5200:ff:fe02:3@7<
                                                              0 64497 i
   *> 2001:db8::6/127  fe80::5200:ff:fe02:3@7<
                                                0             0 64497 ?
   *> 2001:db8:0:1::/64
                       2001:db8::1              0         32768 ?
   *> 2001:db8:0:3::/64
                       2001:db8::5@11<          0         32768 ?
   *> 2001:db8:1::/48  fe80::5200:ff:fe02:3@7<
                                                0             0 64497 ?
   *> 2001:db8:2::/48  fe80::5200:ff:fe02:3@7<
                                                0             0 64497 ?
   *> 2001:db8:3::/48  fe80::5200:ff:fe02:3@7<
                                                0             0 64497 ?


   # show ip route vrf <VRF>
   # show ipv6 route vrf <VRF>

   vyos@Core:~$ show ip route vrf LAN1
   Codes: K - kernel route, C - connected, S - static, R - RIP,
          O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
          T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
          f - OpenFabric,
          > - selected route, * - FIB route, q - queued, r - rejected, b - backup
          t - trapped, o - offload failure

   VRF LAN1:
   B>* 0.0.0.0/0 [20/0] via 10.2.2.2, eth3 (vrf Internet), weight 1, 00:00:38
   S>* 10.0.0.0/24 [1/0] via 10.1.1.2, eth0, weight 1, 00:29:57
   C>* 10.1.1.0/30 is directly connected, eth0, 00:29:59
   B   10.2.2.0/30 [20/0] via 10.2.2.2 (vrf Internet) inactive, weight 1, 00:00:38
   B>* 172.16.0.0/24 [20/0] via 172.16.2.2, eth1 (vrf LAN2), weight 1, 00:00:38
   B>* 192.0.2.0/24 [20/0] via 10.2.2.2, eth3 (vrf Internet), weight 1, 00:00:38
   B>* 198.51.100.0/24 [20/0] via 10.2.2.2, eth3 (vrf Internet), weight 1, 00:00:38
   B>* 203.0.113.0/24 [20/0] via 10.2.2.2, eth3 (vrf Internet), weight 1, 00:00:38

   vyos@Core# run show ipv6 route vrf LAN1
   Codes: K - kernel route, C - connected, S - static, R - RIPng,
          O - OSPFv3, I - IS-IS, B - BGP, N - NHRP, T - Table,
          v - VNC, V - VNC-Direct, A - Babel, F - PBR,
          f - OpenFabric,
          > - selected route, * - FIB route, q - queued, r - rejected, b - backup
          t - trapped, o - offload failure

   VRF LAN1:
   B>* ::/0 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:07:50
   C>* 2001:db8::/127 is directly connected, eth0, 05:33:43
   B>* 2001:db8::6/127 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:07:50
   S>* 2001:db8:0:1::/64 [1/0] via 2001:db8::1, eth0, weight 1, 05:31:03
   B>* 2001:db8:0:3::/64 [20/0] via 2001:db8::5, eth2 (vrf Management), weight 1, 00:07:50
   B>* 2001:db8:1::/48 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:07:50
   B>* 2001:db8:2::/48 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:07:50
   B>* 2001:db8:3::/48 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:07:50
   C>* fe80::/64 is directly connected, eth0, 05:33:43


As we can see in the BGP table any imported route has been injected with a "@"
followed by the VPN id; In the routing table of the VRF, if the route was
installed, we can see -between round brackets- the exported VRF table.

Step 4: End to End verification
-------------------------------


Now we perform some end-to-end testing

- From Management to LAN1/LAN2


.. code-block:: none

   vyos@Management:~$ ping 10.0.0.1 source-address 192.168.0.1
   PING 10.0.0.1 (10.0.0.1) from 192.168.0.1 : 56(84) bytes of data.
   64 bytes from 10.0.0.1: icmp_seq=1 ttl=63 time=1.93 ms
   64 bytes from 10.0.0.1: icmp_seq=2 ttl=63 time=2.12 ms
   64 bytes from 10.0.0.1: icmp_seq=3 ttl=63 time=2.12 ms
   ^C
   --- 10.0.0.1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2005ms
   rtt min/avg/max/mdev = 1.931/2.056/2.123/0.088 ms
   vyos@Management:~$ ping 172.16.0.1 source-address 192.168.0.1
   PING 172.16.0.1 (172.16.0.1) from 192.168.0.1 : 56(84) bytes of data.
   64 bytes from 172.16.0.1: icmp_seq=1 ttl=63 time=1.62 ms
   64 bytes from 172.16.0.1: icmp_seq=2 ttl=63 time=1.75 ms
   ^C
   --- 172.16.0.1 ping statistics ---
   2 packets transmitted, 2 received, 0% packet loss, time 1001ms
   rtt min/avg/max/mdev = 1.621/1.686/1.752/0.065 ms
   vyos@Management:~$ ping 2001:db8:0:1::1 source-address 2001:db8:0:3::1
   PING 2001:db8:0:1::1(2001:db8:0:1::1) from 2001:db8:0:3::1 : 56 data bytes
   64 bytes from 2001:db8:0:1::1: icmp_seq=1 ttl=63 time=2.44 ms
   64 bytes from 2001:db8:0:1::1: icmp_seq=2 ttl=63 time=2.40 ms
   64 bytes from 2001:db8:0:1::1: icmp_seq=3 ttl=63 time=2.41 ms
   ^C
   --- 2001:db8:0:1::1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2003ms
   rtt min/avg/max/mdev = 2.399/2.418/2.442/0.017 ms
   vyos@Management:~$ ping 2001:db8:0:2::1 source-address 2001:db8:0:3::1
   PING 2001:db8:0:2::1(2001:db8:0:2::1) from 2001:db8:0:3::1 : 56 data bytes
   64 bytes from 2001:db8:0:2::1: icmp_seq=1 ttl=63 time=1.66 ms
   64 bytes from 2001:db8:0:2::1: icmp_seq=2 ttl=63 time=1.99 ms
   64 bytes from 2001:db8:0:2::1: icmp_seq=3 ttl=63 time=1.88 ms
   64 bytes from 2001:db8:0:2::1: icmp_seq=4 ttl=63 time=2.32 ms
   ^C
   --- 2001:db8:0:2::1 ping statistics ---
   4 packets transmitted, 4 received, 0% packet loss, time 3005ms
   rtt min/avg/max/mdev = 1.660/1.960/2.315/0.236 ms

- From Management to Outside (fails as intended)



.. code-block:: none

   vyos@Management:~$ show ip route
   Codes: K - kernel route, C - connected, S - static, R - RIP,
          O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
          T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
          f - OpenFabric,
          > - selected route, * - FIB route, q - queued, r - rejected, b - backup
          t - trapped, o - offload failure

   S>* 0.0.0.0/0 [1/0] via 192.168.3.1, eth2, weight 1, 00:01:58
   C>* 192.168.0.0/24 is directly connected, dum0, 00:02:05
   C>* 192.168.3.0/30 is directly connected, eth2, 00:02:03
   vyos@Management:~$ ping 192.0.2.1
   PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.
   From 192.168.3.1 icmp_seq=1 Destination Net Unreachable
   From 192.168.3.1 icmp_seq=2 Destination Net Unreachable
   ^C
   --- 192.0.2.1 ping statistics ---
   2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1002ms

   vyos@Management:~$ ping 195.51.100.1
   PING 195.51.100.1 (195.51.100.1) 56(84) bytes of data.
   From 192.168.3.1 icmp_seq=1 Destination Net Unreachable
   From 192.168.3.1 icmp_seq=2 Destination Net Unreachable
   From 192.168.3.1 icmp_seq=3 Destination Net Unreachable
   ^C
   --- 195.51.100.1 ping statistics ---
   3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2003ms

   vyos@Management:~$ ping 2001:db8:1::1
   PING 2001:db8:1::1(2001:db8:1::1) 56 data bytes
   From 2001:db8::4 icmp_seq=1 Destination unreachable: No route
   From 2001:db8::4 icmp_seq=2 Destination unreachable: No route
   ^C
   --- 2001:db8:1::1 ping statistics ---
   2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1002ms

   vyos@Management:~$ ping 2001:db8:2::1
   PING 2001:db8:2::1(2001:db8:2::1) 56 data bytes
   From 2001:db8::4 icmp_seq=1 Destination unreachable: No route
   From 2001:db8::4 icmp_seq=2 Destination unreachable: No route
   ^C
   --- 2001:db8:2::1 ping statistics ---
   2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1002ms


- LAN1 to Outside



.. code-block:: none

   vyos@LAN1:~$ ping 192.0.2.1 source-address 10.0.0.1
   PING 192.0.2.1 (192.0.2.1) from 10.0.0.1 : 56(84) bytes of data.
   64 bytes from 192.0.2.1: icmp_seq=1 ttl=63 time=1.47 ms
   64 bytes from 192.0.2.1: icmp_seq=2 ttl=63 time=1.41 ms
   64 bytes from 192.0.2.1: icmp_seq=3 ttl=63 time=1.80 ms
   ^C
   --- 192.0.2.1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2004ms
   rtt min/avg/max/mdev = 1.414/1.563/1.803/0.171 ms
   vyos@LAN1:~$ ping 198.51.100.1 source-address 10.0.0.1
   PING 198.51.100.1 (198.51.100.1) from 10.0.0.1 : 56(84) bytes of data.
   64 bytes from 198.51.100.1: icmp_seq=1 ttl=63 time=1.71 ms
   64 bytes from 198.51.100.1: icmp_seq=2 ttl=63 time=1.83 ms
   ^C
   --- 198.51.100.1 ping statistics ---
   2 packets transmitted, 2 received, 0% packet loss, time 1002ms
   rtt min/avg/max/mdev = 1.705/1.766/1.828/0.061 ms
   vyos@LAN1:~$ ping 203.0.113.1 source-address 10.0.0.1
   PING 203.0.113.1 (203.0.113.1) from 10.0.0.1 : 56(84) bytes of data.
   64 bytes from 203.0.113.1: icmp_seq=1 ttl=63 time=1.25 ms
   64 bytes from 203.0.113.1: icmp_seq=2 ttl=63 time=1.88 ms
   ^C
   --- 203.0.113.1 ping statistics ---
   2 packets transmitted, 2 received, 0% packet loss, time 1003ms
   rtt min/avg/max/mdev = 1.249/1.566/1.884/0.317 ms
   vyos@LAN1:~$ ping 2001:db8:1::1 source-address 2001:db8:0:1::1
   PING 2001:db8:1::1(2001:db8:1::1) from 2001:db8:0:1::1 : 56 data bytes
   64 bytes from 2001:db8:1::1: icmp_seq=1 ttl=63 time=2.35 ms
   64 bytes from 2001:db8:1::1: icmp_seq=2 ttl=63 time=2.29 ms
   64 bytes from 2001:db8:1::1: icmp_seq=3 ttl=63 time=2.22 ms
   ^C
   --- 2001:db8:1::1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2004ms
   rtt min/avg/max/mdev = 2.215/2.285/2.352/0.055 ms
   vyos@LAN1:~$ ping 2001:db8:2::1 source-address 2001:db8:0:1::1
   PING 2001:db8:2::1(2001:db8:2::1) from 2001:db8:0:1::1 : 56 data bytes
   64 bytes from 2001:db8:2::1: icmp_seq=1 ttl=63 time=1.37 ms
   64 bytes from 2001:db8:2::1: icmp_seq=2 ttl=63 time=2.68 ms
   64 bytes from 2001:db8:2::1: icmp_seq=3 ttl=63 time=2.00 ms
   ^C
   --- 2001:db8:2::1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2003ms
   rtt min/avg/max/mdev = 1.367/2.015/2.679/0.535 ms


.. note:: we are using "source-address" option cause we are not redistributing
   connected interfaces into BGP on the Core router hence there is no comeback
   route and ping will fail.

- LAN1 to LAN2



.. code-block:: none

   vyos@LAN1:~$ ping 172.16.0.1 source-address 10.0.0.1
   PING 172.16.0.1 (172.16.0.1) from 10.0.0.1 : 56(84) bytes of data.
   64 bytes from 172.16.0.1: icmp_seq=1 ttl=63 time=3.00 ms
   64 bytes from 172.16.0.1: icmp_seq=2 ttl=63 time=2.20 ms
   ^C
   --- 172.16.0.1 ping statistics ---
   2 packets transmitted, 2 received, 0% packet loss, time 1002ms
   rtt min/avg/max/mdev = 2.199/2.600/3.001/0.401 ms
   vyos@LAN1:~$ ping 2001:db8:0:2::1 source 2001:db8:0:1::1
   PING 2001:db8:0:2::1(2001:db8:0:2::1) from 2001:db8:0:1::1 : 56 data bytes
   64 bytes from 2001:db8:0:2::1: icmp_seq=1 ttl=63 time=4.82 ms
   64 bytes from 2001:db8:0:2::1: icmp_seq=2 ttl=63 time=1.95 ms
   64 bytes from 2001:db8:0:2::1: icmp_seq=3 ttl=63 time=1.98 ms
   ^C
   --- 2001:db8:0:2::1 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2003ms
   rtt min/avg/max/mdev = 1.949/2.915/4.815/1.343 ms

***********
Conclusions
***********

Inter-VRF routing is a well-known solution to address complex routing scenarios
that enable -in a dynamic way- to leak routes between VRFs. Is recommended to
take special consideration while designing route-targets and its application as
it can minimize future interventions while creating a new VRF will automatically
take the desired effect in its propagation.

**********
Appendix-A
**********

Full configuration from all devices
===================================

- Core


.. code-block:: none

   set interfaces ethernet eth0 address '10.1.1.1/30'
   set interfaces ethernet eth0 address '2001:db8::/127'
   set interfaces ethernet eth0 vrf 'LAN1'
   set interfaces ethernet eth1 address '172.16.2.1/30'
   set interfaces ethernet eth1 address '2001:db8::2/127'
   set interfaces ethernet eth1 vrf 'LAN2'
   set interfaces ethernet eth2 address '192.168.3.1/30'
   set interfaces ethernet eth2 address '2001:db8::4/127'
   set interfaces ethernet eth2 vrf 'Management'
   set interfaces ethernet eth3 address '10.2.2.1/30'
   set interfaces ethernet eth3 address '2001:db8::6/127'
   set interfaces ethernet eth3 vrf 'Internet'
   set protocols bgp address-family ipv4-unicast
   set protocols bgp system-as '64496'
   set vrf name Internet protocols bgp address-family ipv4-unicast export vpn
   set vrf name Internet protocols bgp address-family ipv4-unicast import vpn
   set vrf name Internet protocols bgp address-family ipv4-unicast rd vpn export '64496:100'
   set vrf name Internet protocols bgp address-family ipv4-unicast route-target vpn export '64496:100'
   set vrf name Internet protocols bgp address-family ipv4-unicast route-target vpn import '64496:1 64496:2'
   set vrf name Internet protocols bgp address-family ipv6-unicast export vpn
   set vrf name Internet protocols bgp address-family ipv6-unicast import vpn
   set vrf name Internet protocols bgp address-family ipv6-unicast rd vpn export '64496:100'
   set vrf name Internet protocols bgp address-family ipv6-unicast route-target vpn export '64496:100'
   set vrf name Internet protocols bgp address-family ipv6-unicast route-target vpn import '64496:1 64496:2'
   set vrf name Internet protocols bgp system-as '64496'
   set vrf name Internet protocols bgp neighbor 10.2.2.2 address-family ipv4-unicast
   set vrf name Internet protocols bgp neighbor 10.2.2.2 remote-as '64497'
   set vrf name Internet protocols bgp neighbor 2001:db8::7 address-family ipv6-unicast
   set vrf name Internet protocols bgp neighbor 2001:db8::7 remote-as '64497'
   set vrf name Internet table '104'
   set vrf name LAN1 protocols bgp address-family ipv4-unicast export vpn
   set vrf name LAN1 protocols bgp address-family ipv4-unicast import vpn
   set vrf name LAN1 protocols bgp address-family ipv4-unicast rd vpn export '64496:1'
   set vrf name LAN1 protocols bgp address-family ipv4-unicast redistribute static
   set vrf name LAN1 protocols bgp address-family ipv4-unicast route-target vpn export '64496:1'
   set vrf name LAN1 protocols bgp address-family ipv4-unicast route-target vpn import '64496:100 64496:50 64496:2'
   set vrf name LAN1 protocols bgp address-family ipv6-unicast export vpn
   set vrf name LAN1 protocols bgp address-family ipv6-unicast import vpn
   set vrf name LAN1 protocols bgp address-family ipv6-unicast rd vpn export '64496:1'
   set vrf name LAN1 protocols bgp address-family ipv6-unicast redistribute static
   set vrf name LAN1 protocols bgp address-family ipv6-unicast route-target vpn export '64496:1'
   set vrf name LAN1 protocols bgp address-family ipv6-unicast route-target vpn import '64496:100 64496:50 64496:2'
   set vrf name LAN1 protocols bgp system-as '64496'
   set vrf name LAN1 protocols static route 10.0.0.0/24 next-hop 10.1.1.2
   set vrf name LAN1 protocols static route6 2001:db8:0:1::/64 next-hop 2001:db8::1
   set vrf name LAN1 table '101'
   set vrf name LAN2 protocols bgp address-family ipv4-unicast export vpn
   set vrf name LAN2 protocols bgp address-family ipv4-unicast import vpn
   set vrf name LAN2 protocols bgp address-family ipv4-unicast rd vpn export '64496:2'
   set vrf name LAN2 protocols bgp address-family ipv4-unicast redistribute static
   set vrf name LAN2 protocols bgp address-family ipv4-unicast route-target vpn export '64496:2'
   set vrf name LAN2 protocols bgp address-family ipv4-unicast route-target vpn import '64496:100 64496:50 64496:1'
   set vrf name LAN2 protocols bgp address-family ipv6-unicast export vpn
   set vrf name LAN2 protocols bgp address-family ipv6-unicast import vpn
   set vrf name LAN2 protocols bgp address-family ipv6-unicast rd vpn export '64496:2'
   set vrf name LAN2 protocols bgp address-family ipv6-unicast redistribute static
   set vrf name LAN2 protocols bgp address-family ipv6-unicast route-target vpn export '64496:2'
   set vrf name LAN2 protocols bgp address-family ipv6-unicast route-target vpn import '64496:100 64496:50 64496:1'
   set vrf name LAN2 protocols bgp system-as '64496'
   set vrf name LAN2 protocols static route 172.16.0.0/24 next-hop 172.16.2.2
   set vrf name LAN2 protocols static route6 2001:db8:0:2::/64 next-hop 2001:db8::3
   set vrf name LAN2 table '102'
   set vrf name Management protocols bgp address-family ipv4-unicast export vpn
   set vrf name Management protocols bgp address-family ipv4-unicast import vpn
   set vrf name Management protocols bgp address-family ipv4-unicast rd vpn export '64496:50'
   set vrf name Management protocols bgp address-family ipv4-unicast redistribute static
   set vrf name Management protocols bgp address-family ipv4-unicast route-target vpn export '64496:50'
   set vrf name Management protocols bgp address-family ipv4-unicast route-target vpn import '64496:1 64496:2'
   set vrf name Management protocols bgp address-family ipv6-unicast export vpn
   set vrf name Management protocols bgp address-family ipv6-unicast import vpn
   set vrf name Management protocols bgp address-family ipv6-unicast rd vpn export '64496:50'
   set vrf name Management protocols bgp address-family ipv6-unicast redistribute static
   set vrf name Management protocols bgp address-family ipv6-unicast route-target vpn export '64496:50'
   set vrf name Management protocols bgp address-family ipv6-unicast route-target vpn import '64496:1 64496:2'
   set vrf name Management protocols bgp system-as '64496'
   set vrf name Management protocols static route 192.168.0.0/24 next-hop 192.168.3.2
   set vrf name Management protocols static route6 2001:db8:0:3::/64 next-hop 2001:db8::5
   set vrf name Management table '103'


- LAN1


.. code-block:: none

   set interfaces dummy dum0 address '10.0.0.1/24'
   set interfaces dummy dum0 address '2001:db8:0:1::1/64'
   set interfaces ethernet eth0 address '10.1.1.2/30'
   set interfaces ethernet eth0 address '2001:db8::1/127'
   set protocols static route 0.0.0.0/0 next-hop 10.1.1.1
   set protocols static route6 ::/0 next-hop 2001:db8::*

- LAN2



.. code-block:: none

   set interfaces dummy dum0 address '172.16.0.1/24'
   set interfaces dummy dum0 address '2001:db8:0:2::1/64'
   set interfaces ethernet eth0 hw-id '50:00:00:03:00:00'
   set interfaces ethernet eth1 address '172.16.2.2/30'
   set interfaces ethernet eth1 address '2001:db8::3/127'
   set protocols static route 0.0.0.0/0 next-hop 172.16.2.1
   set protocols static route6 ::/0 next-hop 2001:db8::2

- Management


.. code-block:: none

   set interfaces dummy dum0 address '192.168.0.1/24'
   set interfaces dummy dum0 address '2001:db8:0:3::1/64'
   set interfaces ethernet eth2 address '192.168.3.2/30'
   set interfaces ethernet eth2 address '2001:db8::5/127'
   set protocols static route 0.0.0.0/0 next-hop 192.168.3.1
   set protocols static route6 ::/0 next-hop 2001:db8::4

- ISP


.. code-block:: none

   set interfaces dummy dum0 address '192.0.2.1/24'
   set interfaces dummy dum0 address '2001:db8:1::1/48'
   set interfaces dummy dum1 address '198.51.100.1/24'
   set interfaces dummy dum1 address '2001:db8:2::1/48'
   set interfaces dummy dum2 address '203.0.113.1/24'
   set interfaces dummy dum2 address '2001:db8:3::1/48'
   set interfaces ethernet eth3 address '10.2.2.2/30'
   set interfaces ethernet eth3 address '2001:db8::7/127'
   set protocols bgp address-family ipv4-unicast redistribute connected
   set protocols bgp address-family ipv6-unicast redistribute connected
   set protocols bgp system-as '64497'
   set protocols bgp neighbor 10.2.2.1 address-family ipv4-unicast default-originate
   set protocols bgp neighbor 10.2.2.1 remote-as '64496'
   set protocols bgp neighbor 2001:db8::6 address-family ipv6-unicast default-originate
   set protocols bgp neighbor 2001:db8::6 remote-as '64496'
   set protocols static route 0.0.0.0/0 next-hop 10.2.2.1
   set protocols static route6 ::/0 next-hop 2001:db8::6

**********
Appendix-B
**********

Route-Filtering
===============


When importing routes using MP-BGP it is possible to filter a subset of them
before are injected in the BGP table. One of the most common case is to use a
route-map with an prefix-list.

- Configuration



We create a prefix-list first and add all the routes we need to.

.. code-block:: none

   # set both ipv4 and ipv6 policies

   set policy prefix-list LAN2-Internet rule 1 action 'permit'
   set policy prefix-list LAN2-Internet rule 1 le '24'
   set policy prefix-list LAN2-Internet rule 1 prefix '198.51.0.0/16'
   set policy prefix-list LAN2-Internet rule 2 action 'permit'
   set policy prefix-list LAN2-Internet rule 2 prefix '192.0.2.0/24'
   set policy prefix-list LAN2-Internet rule 3 action 'permit'
   set policy prefix-list LAN2-Internet rule 3 prefix '192.168.0.0/24'
   set policy prefix-list LAN2-Internet rule 4 action 'permit'
   set policy prefix-list LAN2-Internet rule 4 prefix '10.0.0.0/24'

   set policy prefix-list6 LAN2-Internet-v6 rule 1 action 'permit'
   set policy prefix-list6 LAN2-Internet-v6 rule 1 prefix '2001:db8:1::/48'
   set policy prefix-list6 LAN2-Internet-v6 rule 2 action 'permit'
   set policy prefix-list6 LAN2-Internet-v6 rule 2 prefix '2001:db8:2::/48'
   set policy prefix-list6 LAN2-Internet-v6 rule 3 action 'permit'
   set policy prefix-list6 LAN2-Internet-v6 rule 3 prefix '2001:db8:0:3::/64'
   set policy prefix-list6 LAN2-Internet-v6 rule 4 action 'permit'
   set policy prefix-list6 LAN2-Internet-v6 rule 4 prefix '2001:db8:0:1::/64'

Then add a route-map and reference to above prefix. Consider that the actions
taken inside the prefix will MATCH the routes that will be affected by the
actions inside the rules of the route-map.

.. code-block:: none

   set policy route-map LAN2-Internet rule 1 action 'permit'
   set policy route-map LAN2-Internet rule 1 match ip address prefix-list 'LAN2-Internet'

   set policy route-map LAN2-Internet-v6 rule 1 action 'permit'
   set policy route-map LAN2-Internet-v6 rule 1 match ipv6 address prefix-list 'LAN2-Internet-v6'

We are using a "white list" approach by allowing only what is necessary. In case
that need to implement a "black list" approach then you will need to change the
action in the route-map for a deny BUT you need to add a rule that permits the
rest due to the implicit deny in the route-map.

Then we need to attach the policy to the BGP process. This needs to be under
the import statement in the vrf we need to filter.

.. code-block:: none

   set vrf name LAN2 protocols bgp address-family ipv4-unicast route-map vpn import 'LAN2-Internet'
   set vrf name LAN2 protocols bgp address-family ipv6-unicast route-map vpn import 'LAN2-Internet-v6'


- Verification


.. code-block:: none

   # show ip route vrf LAN2

   B>* 10.0.0.0/24 [20/0] via 10.1.1.2, eth0 (vrf LAN1), weight 1, 00:45:28
   S>* 172.16.0.0/24 [1/0] via 172.16.2.2, eth1, weight 1, 00:45:32
   C>* 172.16.2.0/30 is directly connected, eth1, 00:45:39
   B>* 192.0.2.0/24 [20/0] via 10.2.2.2, eth3 (vrf Internet), weight 1, 00:45:24
   B>* 192.168.0.0/24 [20/0] via 192.168.3.2, eth2 (vrf Managment), weight 1, 00:45:27
   B>* 198.51.100.0/24 [20/0] via 10.2.2.2, eth3 (vrf Internet), weight 1, 00:45:24

   # show ipv6 route vrf LAN2

   C>* 2001:db8::2/127 is directly connected, eth1, 00:46:26
   B>* 2001:db8:0:1::/64 [20/0] via 2001:db8::1, eth0 (vrf LAN1), weight 1, 00:46:17
   S>* 2001:db8:0:2::/64 [1/0] via 2001:db8::3, eth1, weight 1, 00:46:21
   B>* 2001:db8:0:3::/64 [20/0] via 2001:db8::5, eth2 (vrf Managment), weight 1, 00:46:16
   B>* 2001:db8:1::/48 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:46:13
   B>* 2001:db8:2::/48 [20/0] via fe80::5200:ff:fe02:3, eth3 (vrf Internet), weight 1, 00:46:13
   C>* fe80::/64 is directly connected, eth1, 00:46:27

As we can see even if both VRF LAN1 and LAN2 has the same import RTs we are able
to select which routes are effectively imported and installed.