Chapter 53: FRRouting (FRR) - Open Source Routing Suite

Learning Objectives

By the end of this chapter, you will be able to: - Understand FRRouting architecture and capabilities - Deploy FRR containers in ContainerLab environments - Configure multiple routing protocols using FRR - Implement advanced routing features with open source tools - Integrate FRR with commercial network equipment

Introduction to FRRouting (FRR)

What is FRRouting?

FRRouting (FRR) is a free and open source Internet routing protocol suite for Linux and Unix platforms. It implements BGP, OSPF, RIP, IS-IS, PIM, LDP, BFD, and Babel routing protocols. FRR is a fork of Quagga and is actively developed by a community of network engineers and developers.

Key FRR Features

  • Multi-Protocol Support: BGP, OSPF, IS-IS, RIP, PIM, LDP, BFD
  • High Performance: Optimized for modern hardware
  • Standards Compliant: Implements RFC standards
  • Extensible: Plugin architecture for new features
  • Production Ready: Used by major cloud providers and ISPs
  • Container Native: Excellent ContainerLab integration

FRR Architecture

Core Components

  • zebra: Kernel routing manager and interface to other daemons
  • bgpd: BGP daemon
  • ospfd: OSPF daemon
  • ospf6d: OSPFv3 daemon
  • ripd: RIP daemon
  • ripngd: RIPng daemon
  • isisd: IS-IS daemon
  • pimd: PIM daemon
  • ldpd: LDP daemon
  • bfdd: BFD daemon

FRR Lab Environment

Basic FRR Lab Setup

# FRR comprehensive lab
name: frr-routing-lab
prefix: frr

topology:
  nodes:
    # FRR routers
    frr-r1:
      kind: linux
      image: frrouting/frr:latest
      mgmt-ipv4: 172.20.20.10
      exec:
        - ip addr add 10.1.12.1/30 dev eth1
        - ip addr add 10.1.13.1/30 dev eth2
        - ip addr add 192.168.1.1/24 dev eth3
        - ip link set eth1 up
        - ip link set eth2 up
        - ip link set eth3 up
      binds:
        - ./configs/frr-r1:/etc/frr

    frr-r2:
      kind: linux
      image: frrouting/frr:latest
      mgmt-ipv4: 172.20.20.11
      exec:
        - ip addr add 10.1.12.2/30 dev eth1
        - ip addr add 10.1.24.1/30 dev eth2
        - ip addr add 192.168.2.1/24 dev eth3
        - ip link set eth1 up
        - ip link set eth2 up
        - ip link set eth3 up
      binds:
        - ./configs/frr-r2:/etc/frr

    frr-r3:
      kind: linux
      image: frrouting/frr:latest
      mgmt-ipv4: 172.20.20.12
      exec:
        - ip addr add 10.1.13.2/30 dev eth1
        - ip addr add 10.1.34.1/30 dev eth2
        - ip addr add 192.168.3.1/24 dev eth3
        - ip link set eth1 up
        - ip link set eth2 up
        - ip link set eth3 up
      binds:
        - ./configs/frr-r3:/etc/frr

    frr-r4:
      kind: linux
      image: frrouting/frr:latest
      mgmt-ipv4: 172.20.20.13
      exec:
        - ip addr add 10.1.24.2/30 dev eth1
        - ip addr add 10.1.34.2/30 dev eth2
        - ip addr add 192.168.4.1/24 dev eth3
        - ip link set eth1 up
        - ip link set eth2 up
        - ip link set eth3 up
      binds:
        - ./configs/frr-r4:/etc/frr

    # BGP route reflector
    frr-rr:
      kind: linux
      image: frrouting/frr:latest
      mgmt-ipv4: 172.20.20.14
      exec:
        - ip addr add 10.1.15.1/30 dev eth1
        - ip addr add 10.1.25.1/30 dev eth2
        - ip addr add 10.1.35.1/30 dev eth3
        - ip addr add 10.1.45.1/30 dev eth4
        - ip link set eth1 up
        - ip link set eth2 up
        - ip link set eth3 up
        - ip link set eth4 up
      binds:
        - ./configs/frr-rr:/etc/frr

    # Test clients
    client1:
      kind: linux
      image: alpine:latest
      exec:
        - ip addr add 192.168.1.10/24 dev eth1
        - ip route add default via 192.168.1.1

    client2:
      kind: linux
      image: alpine:latest
      exec:
        - ip addr add 192.168.2.10/24 dev eth1
        - ip route add default via 192.168.2.1

    client3:
      kind: linux
      image: alpine:latest
      exec:
        - ip addr add 192.168.3.10/24 dev eth1
        - ip route add default via 192.168.3.1

    client4:
      kind: linux
      image: alpine:latest
      exec:
        - ip addr add 192.168.4.10/24 dev eth1
        - ip route add default via 192.168.4.1

  links:
    # Core network mesh
    - endpoints: ["frr-r1:eth1", "frr-r2:eth1"]
    - endpoints: ["frr-r1:eth2", "frr-r3:eth1"]
    - endpoints: ["frr-r2:eth2", "frr-r4:eth1"]
    - endpoints: ["frr-r3:eth2", "frr-r4:eth2"]

    # Route reflector connections
    - endpoints: ["frr-rr:eth1", "frr-r1:eth4"]
    - endpoints: ["frr-rr:eth2", "frr-r2:eth4"]
    - endpoints: ["frr-rr:eth3", "frr-r3:eth4"]
    - endpoints: ["frr-rr:eth4", "frr-r4:eth4"]

    # Client connections
    - endpoints: ["frr-r1:eth3", "client1:eth1"]
    - endpoints: ["frr-r2:eth3", "client2:eth1"]
    - endpoints: ["frr-r3:eth3", "client3:eth1"]
    - endpoints: ["frr-r4:eth3", "client4:eth1"]

FRR Configuration Files

Basic FRR Configuration Structure

# Create configuration directories
mkdir -p configs/frr-r1 configs/frr-r2 configs/frr-r3 configs/frr-r4 configs/frr-rr

# FRR daemon configuration
cat > configs/frr-r1/daemons << 'EOF'
# FRR daemon configuration
bgpd=yes
ospfd=yes
ospf6d=no
ripd=no
ripngd=no
isisd=no
pimd=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
pbrd=no
bfdd=yes
fabricd=no
vrrpd=no

# Integrated config file
vtysh_enable=yes
zebra_options="  -A 127.0.0.1 -s 90000000"
bgpd_options="   -A 127.0.0.1"
ospfd_options="  -A 127.0.0.1"
bfdd_options="   -A 127.0.0.1"
EOF

OSPF Configuration

# FRR-R1 OSPF Configuration
cat > configs/frr-r1/frr.conf << 'EOF'
frr version 8.4
frr defaults traditional
hostname frr-r1
log syslog informational
service integrated-vtysh-config
!
interface eth1
 description To-FRR-R2
 ip address 10.1.12.1/30
 ip ospf area 0
 ip ospf hello-interval 5
 ip ospf dead-interval 20
!
interface eth2
 description To-FRR-R3
 ip address 10.1.13.1/30
 ip ospf area 0
!
interface eth3
 description LAN-Network
 ip address 192.168.1.1/24
 ip ospf area 1
!
interface lo
 ip address 1.1.1.1/32
 ip ospf area 0
!
router ospf
 ospf router-id 1.1.1.1
 log-adjacency-changes detail
 area 1 range 192.168.1.0/24
 passive-interface eth3
!
line vty
!
EOF

BGP Configuration

# FRR-R1 BGP Configuration
cat > configs/frr-r1/frr.conf << 'EOF'
frr version 8.4
frr defaults traditional
hostname frr-r1
log syslog informational
service integrated-vtysh-config
!
interface eth1
 description To-FRR-R2
 ip address 10.1.12.1/30
!
interface eth2
 description To-FRR-R3
 ip address 10.1.13.1/30
!
interface eth3
 description LAN-Network
 ip address 192.168.1.1/24
!
interface eth4
 description To-Route-Reflector
 ip address 10.1.15.2/30
!
interface lo
 ip address 1.1.1.1/32
!
router bgp 65001
 bgp router-id 1.1.1.1
 bgp log-neighbor-changes
 no bgp default ipv4-unicast
 neighbor 10.1.15.1 remote-as 65001
 neighbor 10.1.15.1 description Route-Reflector
 neighbor 10.1.15.1 update-source lo
 !
 address-family ipv4 unicast
  network 192.168.1.0/24
  neighbor 10.1.15.1 activate
  neighbor 10.1.15.1 route-reflector-client
 exit-address-family
!
line vty
!
EOF

FRR Protocol Configuration

OSPF with FRR

Multi-Area OSPF Setup

# Deploy FRR lab
containerlab deploy -t frr-routing-lab.yml

# Connect to FRR-R1 and configure OSPF
docker exec -it clab-frr-frr-r1 vtysh

# Enter configuration mode
configure terminal

# Configure OSPF
router ospf
 ospf router-id 1.1.1.1
 log-adjacency-changes detail
 area 1 range 192.168.0.0/22
 area 1 stub
 passive-interface eth3
 network 10.1.12.0/30 area 0
 network 10.1.13.0/30 area 0
 network 192.168.1.0/24 area 1
 network 1.1.1.1/32 area 0

# Verify OSPF configuration
show ip ospf neighbor
show ip ospf database
show ip route ospf

OSPF Authentication

# Configure OSPF authentication
interface eth1
 ip ospf message-digest-key 1 md5 SecureOSPFKey123

router ospf
 area 0 authentication message-digest

# Verify authentication
show ip ospf interface eth1

BGP with FRR

eBGP Configuration

# Configure eBGP on FRR-R1
configure terminal

router bgp 65001
 bgp router-id 1.1.1.1
 bgp log-neighbor-changes
 no bgp default ipv4-unicast

 # eBGP neighbor
 neighbor 10.1.12.2 remote-as 65002
 neighbor 10.1.12.2 description FRR-R2-eBGP

 address-family ipv4 unicast
  network 192.168.1.0/24
  neighbor 10.1.12.2 activate
  neighbor 10.1.12.2 soft-reconfiguration inbound
 exit-address-family

# Verify BGP
show bgp summary
show bgp neighbors
show ip route bgp

Route Reflector Configuration

# Configure route reflector on FRR-RR
configure terminal

router bgp 65001
 bgp router-id 5.5.5.5
 bgp cluster-id 1.1.1.1

 # Route reflector clients
 neighbor 1.1.1.1 remote-as 65001
 neighbor 1.1.1.1 update-source lo
 neighbor 2.2.2.2 remote-as 65001
 neighbor 2.2.2.2 update-source lo
 neighbor 3.3.3.3 remote-as 65001
 neighbor 3.3.3.3 update-source lo
 neighbor 4.4.4.4 remote-as 65001
 neighbor 4.4.4.4 update-source lo

 address-family ipv4 unicast
  neighbor 1.1.1.1 activate
  neighbor 1.1.1.1 route-reflector-client
  neighbor 2.2.2.2 activate
  neighbor 2.2.2.2 route-reflector-client
  neighbor 3.3.3.3 activate
  neighbor 3.3.3.3 route-reflector-client
  neighbor 4.4.4.4 activate
  neighbor 4.4.4.4 route-reflector-client
 exit-address-family

IS-IS with FRR

Basic IS-IS Configuration

# Enable IS-IS daemon
# Edit /etc/frr/daemons: isisd=yes

# Configure IS-IS
configure terminal

router isis 1
 net 49.0001.0000.0000.0001.00
 is-type level-2-only
 log-adjacency-changes

interface eth1
 ip router isis 1
 isis circuit-type level-2-only
 isis hello-interval 3
 isis hello-multiplier 3

interface lo
 ip router isis 1
 isis circuit-type level-2-only
 isis passive

# Verify IS-IS
show isis neighbor
show isis database
show ip route isis

Advanced FRR Features

BFD (Bidirectional Forwarding Detection)

# Configure BFD for fast convergence
configure terminal

# Enable BFD globally
bfd
 peer 10.1.12.2
  detect-multiplier 3
  receive-interval 300
  transmit-interval 300
 exit

# Enable BFD for OSPF
router ospf
 bfd all-interfaces

# Enable BFD for BGP
router bgp 65001
 neighbor 10.1.12.2 bfd

# Verify BFD
show bfd peers
show bfd peer 10.1.12.2

Route Maps and Filtering

# Configure route maps
configure terminal

# Create access lists
ip prefix-list CUSTOMER-ROUTES seq 10 permit 192.168.0.0/16 le 24
ip prefix-list PROVIDER-ROUTES seq 10 permit 0.0.0.0/0 le 32

# Create route map
route-map CUSTOMER-IN permit 10
 match ip address prefix-list CUSTOMER-ROUTES
 set local-preference 200
route-map CUSTOMER-IN permit 20
 set local-preference 100

# Apply to BGP neighbor
router bgp 65001
 neighbor 10.1.12.2 route-map CUSTOMER-IN in

# Verify route map
show route-map
show bgp neighbors 10.1.12.2 received-routes

Multicast with PIM

# Enable PIM daemon
# Edit /etc/frr/daemons: pimd=yes

# Configure PIM
configure terminal

# Enable multicast forwarding
ip multicast-routing

# Configure PIM on interfaces
interface eth1
 ip pim sparse-mode
 ip igmp

interface eth2
 ip pim sparse-mode
 ip igmp

# Configure RP (Rendezvous Point)
ip pim rp 1.1.1.1 224.0.0.0/4

# Verify PIM
show ip pim neighbor
show ip pim rp-info
show ip mroute

FRR Integration with Commercial Equipment

FRR with Cisco Integration

# Mixed FRR and Cisco lab
name: frr-cisco-integration
topology:
  nodes:
    frr-router:
      kind: linux
      image: frrouting/frr:latest
      exec:
        - ip addr add 10.1.12.1/30 dev eth1
        - ip link set eth1 up
      binds:
        - ./configs/frr-mixed:/etc/frr

    cisco-router:
      kind: cisco_iosxe
      image: cisco/iosxe:latest
      startup-config: |
        hostname Cisco-Router
        !
        interface GigabitEthernet0/0/0
         ip address 10.1.12.2 255.255.255.252
         no shutdown
        !
        router bgp 65002
         bgp router-id 2.2.2.2
         neighbor 10.1.12.1 remote-as 65001
         network 203.0.113.0 mask 255.255.255.0
        !

  links:
    - endpoints: ["frr-router:eth1", "cisco-router:eth1"]

Protocol Interoperability Testing

# Test OSPF interoperability
docker exec -it clab-frr-cisco-integration-frr-router vtysh -c "show ip ospf neighbor"
docker exec -it clab-frr-cisco-integration-cisco-router cli -c "show ip ospf neighbor"

# Test BGP interoperability
docker exec -it clab-frr-cisco-integration-frr-router vtysh -c "show bgp summary"
docker exec -it clab-frr-cisco-integration-cisco-router cli -c "show bgp summary"

FRR Monitoring and Troubleshooting

FRR Diagnostic Commands

# System information
show version
show memory
show thread cpu

# Interface information
show interface
show interface eth1
show ip interface

# Routing information
show ip route
show ip route summary
show ip route 192.168.1.0/24

# Protocol-specific commands
show ip ospf
show ip ospf neighbor detail
show ip ospf database
show bgp summary
show bgp neighbors
show isis neighbor
show bfd peers

FRR Logging and Debugging

# Configure logging
configure terminal
log file /var/log/frr/frr.log informational
log syslog informational

# Enable debugging (use carefully)
debug ospf packet all
debug bgp updates
debug isis adj-packets

# View logs
show logging

Performance Monitoring

# Monitor FRR performance
show thread cpu
show memory
show zebra

# Interface statistics
show interface eth1
show ip route summary

# Protocol statistics
show ip ospf statistics
show bgp statistics

FRR Automation and Scripting

FRR Configuration Automation

#!/usr/bin/env python3
# frr_config_manager.py
import subprocess
import json
import time

class FRRManager:
    def __init__(self, container_name):
        self.container_name = container_name

    def execute_vtysh_command(self, command):
        """Execute vtysh command in FRR container"""
        cmd = f"docker exec {self.container_name} vtysh -c '{command}'"
        result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
        return result.stdout, result.stderr

    def configure_ospf(self, router_id, networks):
        """Configure OSPF on FRR router"""
        commands = [
            "configure terminal",
            f"router ospf",
            f"ospf router-id {router_id}",
            "log-adjacency-changes detail"
        ]

        for network in networks:
            commands.append(f"network {network['network']} area {network['area']}")

        commands.append("exit")

        for cmd in commands:
            stdout, stderr = self.execute_vtysh_command(cmd)
            if stderr:
                print(f"Error executing '{cmd}': {stderr}")

    def configure_bgp(self, asn, router_id, neighbors):
        """Configure BGP on FRR router"""
        commands = [
            "configure terminal",
            f"router bgp {asn}",
            f"bgp router-id {router_id}",
            "bgp log-neighbor-changes",
            "no bgp default ipv4-unicast"
        ]

        for neighbor in neighbors:
            commands.extend([
                f"neighbor {neighbor['ip']} remote-as {neighbor['asn']}",
                f"neighbor {neighbor['ip']} description {neighbor.get('description', '')}",
                "address-family ipv4 unicast",
                f"neighbor {neighbor['ip']} activate",
                "exit-address-family"
            ])

        commands.append("exit")

        for cmd in commands:
            stdout, stderr = self.execute_vtysh_command(cmd)
            if stderr:
                print(f"Error executing '{cmd}': {stderr}")

    def get_routing_table(self):
        """Get routing table from FRR"""
        stdout, stderr = self.execute_vtysh_command("show ip route json")
        if not stderr:
            try:
                return json.loads(stdout)
            except json.JSONDecodeError:
                return None
        return None

    def get_bgp_summary(self):
        """Get BGP summary from FRR"""
        stdout, stderr = self.execute_vtysh_command("show bgp summary json")
        if not stderr:
            try:
                return json.loads(stdout)
            except json.JSONDecodeError:
                return None
        return None

# Usage example
if __name__ == '__main__':
    frr = FRRManager('clab-frr-frr-r1')

    # Configure OSPF
    networks = [
        {'network': '10.1.12.0/30', 'area': '0'},
        {'network': '192.168.1.0/24', 'area': '1'}
    ]
    frr.configure_ospf('1.1.1.1', networks)

    # Configure BGP
    neighbors = [
        {'ip': '10.1.12.2', 'asn': '65002', 'description': 'FRR-R2'}
    ]
    frr.configure_bgp('65001', '1.1.1.1', neighbors)

    # Get routing information
    routes = frr.get_routing_table()
    if routes:
        print("Routing table:", json.dumps(routes, indent=2))

FRR Best Practices

Configuration Management

  1. Version Control: Store FRR configurations in Git
  2. Templating: Use Jinja2 templates for consistent configs
  3. Validation: Test configurations before deployment
  4. Backup: Regular configuration backups
  5. Documentation: Document network design and changes

Performance Optimization

# Optimize FRR performance
configure terminal

# Increase BGP keepalive frequency
router bgp 65001
 timers bgp 30 90

# Optimize OSPF timers
router ospf
 timers throttle spf 200 400 10000
 timers throttle lsa 200 400 10000

# Enable BFD for fast convergence
bfd
 peer 10.1.12.2
  detect-multiplier 3
  receive-interval 100
  transmit-interval 100

Security Hardening

# FRR security configuration
configure terminal

# BGP security
router bgp 65001
 neighbor 10.1.12.2 password SecureBGPKey123
 neighbor 10.1.12.2 ttl-security hops 1

# OSPF security
interface eth1
 ip ospf message-digest-key 1 md5 SecureOSPFKey456

router ospf
 area 0 authentication message-digest

# Access control
access-list 10 permit 10.1.12.0 0.0.0.3
line vty
 access-class 10 in

Summary

FRRouting provides a powerful, open-source alternative to commercial routing platforms. Its comprehensive protocol support, container-native design, and active development community make it an excellent choice for learning, testing, and production deployments. Understanding FRR capabilities enables cost-effective network implementations while maintaining enterprise-grade functionality.

Key concepts covered: - FRR architecture and daemon structure - Multi-protocol routing configuration (OSPF, BGP, IS-IS) - Advanced features (BFD, route maps, multicast) - Integration with commercial equipment - Automation and monitoring techniques - Performance optimization and security

In the next chapter, we’ll explore VyOS, another powerful open-source network operating system with comprehensive routing and security features.

Review Questions

  1. What are the main advantages of FRR over commercial routing platforms?
  2. How do you configure multi-area OSPF in FRR?
  3. What is the role of the zebra daemon in FRR architecture?
  4. How do you implement BGP route reflection with FRR?
  5. What are best practices for FRR security hardening?

Hands-on Exercises

Exercise 1: Basic FRR Deployment

  1. Deploy the FRR routing lab
  2. Configure OSPF on all routers
  3. Verify neighbor relationships and routing tables
  4. Test end-to-end connectivity

Exercise 2: BGP Configuration

  1. Configure eBGP between different autonomous systems
  2. Implement route reflector for iBGP scaling
  3. Apply route maps for traffic engineering
  4. Monitor BGP convergence and path selection

Exercise 3: Advanced Features

  1. Configure BFD for fast convergence
  2. Implement IS-IS as alternative IGP
  3. Set up PIM for multicast routing
  4. Test protocol interoperability with commercial equipment

Exercise 4: FRR Automation

  1. Create Python scripts for FRR configuration management
  2. Implement automated monitoring and alerting
  3. Develop configuration templates and validation
  4. Build CI/CD pipeline for FRR deployments

Additional Resources