Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

An overview of virtual routing and forwarding (VRF) in Linux

January 8, 2025
Antoine Tenart
Related topics:
LinuxSystem DesignVirtualization
Related products:
Red Hat Enterprise Linux

Share:

    Virtual routing and forwarding (VRF) is a network virtualization technique allowing traffic isolation at the layer 3 (L3) of the OSI model by creating independent routing and forwarding domains. It is essentially the combination of a separate routing table and associated network interfaces.

    Other networking techniques exist but are operating at a different levels—such as VLAN and network namespaces, respectively at the layer 2 and at the device level. Those techniques can be combined, e.g., a VRF can be part of a network namespace and/or VLANs can be attached to a VRF. Note that a network namespace might look like a way to emulate a VRF but they differ in how traffic is handled, notably VRF does not impact layer 2 (L2) traffic.

    In the Linux kernel VRF is supported under the CONFIG_NET_VRF build configuration option.

    Use cases

    As we saw, a VRF is used to isolate L3 traffic. As such it can be used in multi-tenancy environments to isolate customers or to support overlapping networks, as L3 addresses and routes are scoped to a given VRF. When VRF was introduced, it was used in combination with MultiProtocol Label Switching (MPLS), which can be used to allow overlapping traffic to be routed in the same backbone. Because of this, strictly speaking, when VRF is used without MPLS it is called "VRF Lite". We'll keep referring to "VRF" in this article.

    Another use case is to have a clear separation between the management network and the data plane. In short and depending on the requirements, VRF has value for both routing packets and at the endpoints.

    Linux implementation

    In Linux, a VRF domain is represented by a virtual L3 network device and packets (ingress and egress) are flowing through it. This has the advantage of providing a single point to attach TC and netfilter rules, to dump non-forwarding traffic for debugging or for making applications "VRF-aware" by binding sockets to the VRF device. The VRF device also acts as a parent for interfaces part of the domain (note that a given network interface can only be part of a single domain). It can also be nested under a network namespace to combine both features.

    In addition to the VRF interface, a number of techniques are used which are not specific to VRF: a dedicated routing table per VRF domain and routing policy (ip rules), for instance.

    This design—mixing VRF specific techniques and non-VRF ones—is a key point to understand how VRF is implemented in Linux: the VRF implementation is not entirely isolated from the rest of the stack. As such, configuring a VRF implies managing its associated network interface but also handling policy rules and routing tables. The combination of all those techniques provides the routing and forwarding domains.

    Under the hood

    When a packet is received on an interface, the route lookup is redirected to the right table using policy routing. When a packet is sent, the device is set to the VRF parent device which will ensure the right table is used for the lookup.

    VRF in action

    As a VRF domain is represented by a virtual interface on Linux, adding a new VRF domain is similar and as simple as adding other kinds of virtual interfaces. The usual tools can be used, such as iproute2 or nmcli. When adding a new VRF device, a dedicated routing table and (if it does not exist yet) special L3 FIB rule (policy routing) are automatically added. The policy routing rule will direct lookups for matching packets to the routing table associated with the VRF domain.

    L3-enabled network devices that should be part of the VRF domain are then added by making them children of the VRF device. Their local and connected routes are automatically moved to the VRF associated routing table but other routes depending on the device are dropped. Note that because of backward compatibility, global IPv6 addresses are lost by default (this is controlled by the net.ipv6.conf.all.keep_addr_on_down parameter).

    Let's add a VRF domain and see what happens:

    $ ip rule show
    0:        from all lookup local
    32766:    from all lookup main
    32767:    from all lookup default
    $ ip -6 rule show
    0:        from all lookup local
    32766:    from all lookup main
    
    $ ip link add vrf42 type vrf table 42
    $ ip link set vrf42 up
    $ ip -d link show vrf42
    4: vrf42: <NOARP,MASTER,UP,LOWER_UP> mtu 65575 qdisc noqueue state UP mode DEFAULT group default qlen 1000
       link/ether be:d1:bb:4e:6f:be brd ff:ff:ff:ff:ff:ff promiscuity 0 allmulti 0 minmtu 1280 maxmtu 65575
       vrf table 42 ...
       
    $ ip rule show
    0:        from all lookup local
    1000:     from all lookup [l3mdev-table]
    32766:    from all lookup main
    32767:    from all lookup default
    $ ip -6 rule show
    0:        from all lookup local
    1000:     from all lookup [l3mdev-table]
    32766:    from all lookup main

    In the above example we can see adding a new VRF device automatically added a new routing table (table 42) and rules for VRF devices were added in the routing policy with a special [l3mdev-table] lookup. A single rule (per-protocol) is used for all VRF devices.

    To add existing devices to the VRF domain, we can then use ip link set dev <device> master vrf42.

    For an example on how to do the above using nmcli, see this article.

    Note on the default route order

    As shown previously, the policy routing rules for VRF route lookups are added with a priority of 1000. As a consequence, rules with an higher priority (lower number) can match before the VRF one. By default this happens for the local table rule. See below:

    $ ip -6 rule
    0:        from all lookup local
    1000:     from all lookup [l3mdev-table]
    32766:    from all lookup main
    $ ip -6 route show table local
    local ::1 dev lo proto kernel metric 0 pref medium

    Packets sent to ::1 will be delivered to the lo interface in the default domain even if ::1 is also set to an interface in the VRF:

    $ ip -6 address add ::1/128 dev vrf42
    $ ip -6 address show lo
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
       inet6 ::1/128 scope host
          valid_lft forever preferred_lft forever
    $ ip -6 address show vrf42
    32: vrf42: <NOARP,MASTER,UP,LOWER_UP> mtu 65575 qdisc noqueue state UP group default qlen 1000
       inet6 ::1/128 scope host
          valid_lft forever preferred_lft forever
    $ ip -6 route get ::1
    local ::1 from :: dev lo table local proto kernel src ::1 metric 0 pref medium
    $ ip -6 route get ::1 dev vrf42
    local ::1 from :: dev lo table local proto kernel src ::1 metric 0 pref medium

    Similar behavior can be seen for all policy routing rules matching before the VRF one. This can be leveraged to have a fine-grained configuration: rules can be added before, per-VRF rules can be used instead of the global one, or the VRF specific rule can be deleted or reordered.

    Making applications VRF-aware

    By default applications are not bound to any routing domain. Programs we want to be VRF-aware must explicitly do so. This can be done in various ways, as stated in man ip vrf: "A process can specify a VRF using several APIs -- binding the socket to the VRF device using SO_BINDTODEVICE, setting the VRF association using IP_UNICAST_IF or IPV6_UNICAST_IF, or specifying the VRF for a specific message using IP_PKTINFO or IPV6_PKTINFO."

    Sometimes existing applications do not implement the above. For those cases, all sockets of a program can be bound to the VRF device (SO_BINDTODEVICE) using ip vrf exec <vrf device> <cmd>:

    $ ip vrf exec vrf42 python3 -m http.server &
    $ ip vrf pids vrf42
     788  python3

    By default the scope of unbound sockets and bound (to a VRF device) ones do not cross for TCP and UDP. This means that packets received on interfaces in a VRF domain won't be delivered to unbound sockets outside the domain. This behavior is controllable using two sysctl parameters:

    $ sysctl -w net.ipv4.tcp_l3mdev_accept=1
    $ sysctl -w net.ipv4.udp_l3mdev_accept=1

    For RAW sockets a parameter exists as well but is enabled by default (for backward compatibility): net.ipv4.raw_l3mdev_accept.

    Routing between VRFs

    On a system hosting multiple VRF domains, if the networks aren't overlapping, routing between the domains can be as simple as adding a route entry. E.g., in order to route packets 1111:1::/64 -> 1111:2::/64 from vrf1 to vrf2 (and vice versa):

    $ sysctl -w net.ipv6.conf.all.forwarding=1
    $ ip -6 route add 1111:2::/64 dev vrf2 table 41
    $ ip -6 route add 1111:1::/64 dev vrf1 table 42

    Conclusion

    VRF domains are a lightweight solution for isolating L3 traffic and are useful in a number of cases in both routers and endpoints. On Linux, the feature is built on top and reusing existing features (routing tables, policy routing) which allows great flexibility in configuring the desired behavior. However, this also requires to understand the big picture and how everything play with the rest.

    Related Posts

    • What's new in Red Hat Enterprise Linux 9.4?

    • Virtualized database I/O performance improvements in RHEL 9.4

    • How to use Debezium SMT with Groovy to filter routing events

    • Modernizing Pedal: API management for modern system design and administration

    • An update on packet drop reasons in Linux

    Recent Posts

    • Ollama or vLLM? How to choose the right LLM serving tool for your use case

    • How to build a Model-as-a-Service platform

    • How Quarkus works with OpenTelemetry on OpenShift

    • Our top 10 articles of 2025 (so far)

    • The benefits of auto-merging GitHub and GitLab repositories

    What’s up next?

    This systemd Cheat Sheet presents the most common uses of systemctl, along with journalctl for displaying information about systemd activities from its logs.

    Get the cheat sheet
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue