# FRRouting (FRR) FRRouting (FRR) is a free, open-source Internet routing protocol suite for Linux and Unix platforms. It implements major routing protocols including BGP, OSPF, RIP, IS-IS, PIM, LDP, BFD, Babel, PBR, EIGRP, NHRP, and VRRP, providing enterprise-grade routing functionality for both IPv4 and IPv6 networks. FRR runs on nearly all distributions of Linux and BSD, supporting all modern CPU architectures. The project originated as a fork of Quagga and maintains a modular architecture where each routing protocol runs as a separate daemon. These daemons communicate with the central Zebra daemon, which manages the kernel routing table and interface configuration. This design allows administrators to run only the protocols they need while maintaining a unified configuration interface through vtysh, the integrated shell that provides Cisco-like CLI syntax. FRR is actively developed and widely deployed in production networks, data centers, and cloud environments. ## Command-Line Interface (CLI) VTY shell for unified router configuration vtysh provides an integrated command-line interface to configure and monitor all FRR routing daemons through a single session. It connects to individual protocol daemons (bgpd, ospfd, zebra, etc.) via Unix domain sockets and aggregates their configurations into a unified interface with Cisco IOS-style commands. ```bash # Start interactive vtysh shell vtysh # Execute single command vtysh -c "show ip bgp summary" # Execute multiple commands vtysh -c "configure terminal" -c "router bgp 65000" -c "neighbor 10.0.0.1 remote-as 65001" # Load configuration from file vtysh -b -f /etc/frr/frr.conf # Show running configuration vtysh -c "show running-config" # Write configuration to file vtysh -c "write memory" # Example output for "show ip bgp summary": # BGP router identifier 10.0.0.1, local AS number 65000 # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd # 10.0.0.2 4 65001 1234 1235 0 0 0 01:23:45 150 ``` ## Zebra Daemon Core routing table and interface management The zebra daemon serves as the central hub in FRR's architecture, managing the kernel routing table (RIB/FIB), interface configuration, and route redistribution between different routing protocol daemons. All protocol daemons communicate with zebra via the ZAPI (Zebra API) protocol. ```c /* Connect to zebra daemon from protocol daemon */ #include "zclient.h" struct zclient *zclient; /* Initialize zclient connection */ zclient = zclient_new(master, &zclient_options, NULL, 0); zclient->zebra_connected = my_zebra_connected; zclient->interface_add = my_interface_add; zclient->interface_delete = my_interface_delete; zclient->interface_address_add = my_interface_address_add; zclient->ipv4_route_add = my_route_add; zclient->ipv4_route_delete = my_route_delete; zclient_init(zclient, ZEBRA_ROUTE_OSPF, 0, &ospfd_privs); /* Install route to kernel via zebra */ struct zapi_route api; memset(&api, 0, sizeof(api)); api.type = ZEBRA_ROUTE_OSPF; api.instance = 0; api.flags = 0; api.prefix.family = AF_INET; api.prefix.prefixlen = 24; inet_pton(AF_INET, "10.1.1.0", &api.prefix.u.prefix4); struct zapi_nexthop *nexthop = &api.nexthops[0]; nexthop->type = NEXTHOP_TYPE_IPV4; inet_pton(AF_INET, "192.168.1.1", &nexthop->gate.ipv4); nexthop->ifindex = if_nametoindex("eth0"); api.nexthop_num = 1; zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); ``` ## BGP Daemon (bgpd) Border Gateway Protocol implementation bgpd implements BGP-4 (RFC 4271) with extensive support for modern BGP features including route reflectors, confederation, route filtering, MPLS VPN, EVPN, flowspec, and multiprotocol extensions for IPv6, multicast, and L3VPN. It handles peering sessions, route advertisement, and policy-based routing decisions. ```bash # Configure BGP instance vtysh << EOF configure terminal router bgp 65000 bgp router-id 10.0.0.1 neighbor 10.0.0.2 remote-as 65001 neighbor 10.0.0.2 description "External peer ISP1" neighbor 10.0.0.2 update-source eth0 neighbor 192.168.1.1 remote-as 65000 neighbor 192.168.1.1 description "iBGP peer" ! address-family ipv4 unicast network 172.16.0.0/16 neighbor 10.0.0.2 activate neighbor 10.0.0.2 prefix-list OUT-TO-ISP1 out neighbor 192.168.1.1 activate neighbor 192.168.1.1 next-hop-self exit-address-family ! address-family ipv6 unicast network 2001:db8::/32 neighbor 10.0.0.2 activate exit-address-family exit ! ip prefix-list OUT-TO-ISP1 seq 10 permit 172.16.0.0/16 ip prefix-list OUT-TO-ISP1 seq 20 deny any exit write memory EOF # Monitor BGP peers vtysh -c "show ip bgp summary" vtysh -c "show ip bgp neighbors 10.0.0.2 advertised-routes" vtysh -c "show ip bgp neighbors 10.0.0.2 received-routes" # Check BGP routing table vtysh -c "show ip bgp" vtysh -c "show ip bgp 172.16.1.0/24" ``` ## OSPF Daemon (ospfd) Open Shortest Path First v2 implementation ospfd implements OSPFv2 (RFC 2328) for IPv4 dynamic routing within autonomous systems. It supports multiple areas, virtual links, route summarization, stub areas, NSSA, authentication, and BFD integration for fast failure detection. ```bash # Configure OSPF routing vtysh << EOF configure terminal router ospf ospf router-id 10.0.0.1 log-adjacency-changes detail passive-interface default no passive-interface eth0 no passive-interface eth1 network 10.0.0.0/24 area 0.0.0.0 network 192.168.1.0/24 area 0.0.0.1 area 0.0.0.1 stub area 0.0.0.1 range 192.168.0.0/16 redistribute connected redistribute static exit ! interface eth0 ip ospf authentication message-digest ip ospf message-digest-key 1 md5 MySecretPassword ip ospf cost 10 ip ospf hello-interval 5 ip ospf dead-interval 20 ip ospf priority 100 exit write memory EOF # Monitor OSPF state vtysh -c "show ip ospf neighbor" vtysh -c "show ip ospf interface" vtysh -c "show ip ospf database" vtysh -c "show ip ospf route" # Debug OSPF events vtysh -c "debug ospf event" vtysh -c "debug ospf packet all" ``` ## Route Maps Policy-based routing and redistribution control Route maps provide powerful match-and-set capabilities for filtering and modifying routes during redistribution, import/export, and policy-based routing. They operate similarly to Cisco IOS route-maps with match conditions and set actions. ```bash # Configure route maps for BGP policy vtysh << EOF configure terminal ! # Match routes and modify attributes route-map INBOUND-FILTER permit 10 description "Allow specific prefixes with local-pref" match ip address prefix-list CUSTOMER-PREFIXES match as-path AS-PATH-FILTER set local-preference 200 set metric 50 set community 65000:100 additive exit ! route-map INBOUND-FILTER permit 20 description "Allow other routes with default settings" exit ! route-map INBOUND-FILTER deny 30 exit ! # Define prefix list ip prefix-list CUSTOMER-PREFIXES seq 5 permit 172.16.0.0/16 le 24 ip prefix-list CUSTOMER-PREFIXES seq 10 permit 10.0.0.0/8 le 24 ! # Define AS path filter bgp as-path access-list AS-PATH-FILTER permit ^65001_ ! # Apply to BGP neighbor router bgp 65000 neighbor 10.0.0.2 route-map INBOUND-FILTER in exit ! # Route map for redistribution route-map REDIS-TO-OSPF permit 10 match ip address prefix-list CONNECTED-NETWORKS set metric 100 set metric-type type-1 exit ! router ospf redistribute bgp route-map REDIS-TO-OSPF exit write memory EOF # Verify route map application vtysh -c "show route-map INBOUND-FILTER" vtysh -c "show ip bgp neighbors 10.0.0.2 routes" ``` ## VRF (Virtual Routing and Forwarding) Network isolation and multi-tenancy VRF support allows multiple isolated routing tables to coexist on a single router, enabling network segmentation, multi-tenancy, and MPLS L3VPN scenarios. Each VRF maintains separate routing and forwarding tables. ```bash # Configure VRFs vtysh << EOF configure terminal ! # Create VRF instances vrf CUSTOMER-A vni 10010 exit ! vrf CUSTOMER-B vni 10020 exit ! # Assign interfaces to VRFs interface eth1 ip address 192.168.10.1/24 vrf CUSTOMER-A exit ! interface eth2 ip address 192.168.20.1/24 vrf CUSTOMER-B exit ! # Configure BGP per VRF router bgp 65000 vrf CUSTOMER-A bgp router-id 10.0.0.1 neighbor 192.168.10.2 remote-as 65100 address-family ipv4 unicast redistribute connected redistribute static exit-address-family exit ! router bgp 65000 vrf CUSTOMER-B bgp router-id 10.0.0.2 neighbor 192.168.20.2 remote-as 65200 address-family ipv4 unicast redistribute connected exit-address-family exit ! # Configure OSPF per VRF router ospf vrf CUSTOMER-A ospf router-id 10.0.1.1 network 192.168.10.0/24 area 0 exit write memory EOF # Monitor VRF routing tables vtysh -c "show vrf" vtysh -c "show ip route vrf CUSTOMER-A" vtysh -c "show ip bgp vrf CUSTOMER-A" vtysh -c "show ip ospf vrf CUSTOMER-A neighbor" ``` ## BFD (Bidirectional Forwarding Detection) Fast failure detection for routing protocols BFD provides sub-second failure detection between routers, allowing rapid convergence when integrated with routing protocols like BGP, OSPF, and IS-IS. The bfdd daemon manages BFD sessions independently of protocol daemons. ```bash # Configure BFD globally vtysh << EOF configure terminal bfd profile fast-detection detect-multiplier 3 receive-interval 300 transmit-interval 300 exit ! profile slow-detection detect-multiplier 5 receive-interval 1000 transmit-interval 1000 exit exit ! # Enable BFD for OSPF neighbors interface eth0 ip ospf bfd ip ospf bfd profile fast-detection exit ! # Enable BFD for BGP peers router bgp 65000 neighbor 10.0.0.2 remote-as 65001 neighbor 10.0.0.2 bfd neighbor 10.0.0.2 bfd profile fast-detection exit ! # Static BFD peer configuration bfd peer 10.0.0.2 interface eth0 detect-multiplier 3 receive-interval 300 transmit-interval 300 exit exit write memory EOF # Monitor BFD sessions vtysh -c "show bfd peers" vtysh -c "show bfd peers detail" vtysh -c "show bfd peers 10.0.0.2" ``` ## Prefix Lists and Access Lists Route filtering and matching Prefix lists and access lists provide granular control over route filtering, matching specific IP prefixes with optional prefix length ranges. These are fundamental building blocks for route maps and redistribution policies. ```bash # Configure prefix lists vtysh << EOF configure terminal ! # IPv4 prefix list with exact and range matches ip prefix-list ALLOWED-NETWORKS seq 5 permit 10.0.0.0/8 le 24 ip prefix-list ALLOWED-NETWORKS seq 10 permit 172.16.0.0/12 le 24 ip prefix-list ALLOWED-NETWORKS seq 15 permit 192.168.0.0/16 le 28 ip prefix-list ALLOWED-NETWORKS seq 100 deny any ! # IPv6 prefix list ipv6 prefix-list ALLOWED-V6 seq 5 permit 2001:db8::/32 le 48 ipv6 prefix-list ALLOWED-V6 seq 10 deny any ! # AS path access list for BGP bgp as-path access-list AS-PATH-UPSTREAM permit ^65001_ bgp as-path access-list AS-PATH-UPSTREAM permit ^65002_ bgp as-path access-list AS-PATH-UPSTREAM deny .* ! # Community list bgp community-list standard CUSTOMER-ROUTES permit 65000:100 bgp community-list standard CUSTOMER-ROUTES permit 65000:200 bgp community-list expanded REGIONAL permit 65000:[1-5]00 ! # Apply to BGP neighbor router bgp 65000 neighbor 10.0.0.2 prefix-list ALLOWED-NETWORKS in neighbor 10.0.0.2 filter-list AS-PATH-UPSTREAM in exit ! # Apply to OSPF distribution router ospf distribute-list prefix ALLOWED-NETWORKS in eth0 exit write memory EOF # Display prefix lists vtysh -c "show ip prefix-list" vtysh -c "show ip prefix-list ALLOWED-NETWORKS" vtysh -c "show bgp as-path-access-list" ``` ## Static Routing Manual route configuration Static routes provide fixed routing entries that don't change based on network conditions. The staticd daemon manages static routes separately from dynamic routing protocols, allowing centralized static route configuration. ```bash # Configure static routes vtysh << EOF configure terminal ! # Basic IPv4 static routes ip route 10.1.0.0/16 192.168.1.254 ip route 10.2.0.0/16 eth0 192.168.1.1 ! # Static route with administrative distance ip route 172.16.0.0/12 10.0.0.1 50 ! # Null route for blackholing ip route 192.0.2.0/24 Null0 ! # IPv6 static routes ipv6 route 2001:db8:1::/48 2001:db8::1 ipv6 route 2001:db8:2::/48 eth1 fe80::1 ! # VRF-aware static route ip route 10.10.0.0/16 192.168.100.1 vrf CUSTOMER-A ! # Backup route with higher distance ip route 0.0.0.0/0 203.0.113.1 name "Primary Gateway" ip route 0.0.0.0/0 203.0.113.2 254 name "Backup Gateway" ! # Static route with BFD monitoring ip route 10.5.0.0/16 192.168.5.1 bfd exit write memory EOF # Verify static routes vtysh -c "show ip route static" vtysh -c "show ipv6 route static" vtysh -c "show ip route 10.1.0.0/16" ``` ## FRR Library API Core daemon initialization and event loop The libfrr library provides common infrastructure for all FRR daemons including command-line parsing, configuration management, VTY interface, logging, privilege handling, and the main event loop using the frrevent (formerly thread) system. ```c /* Minimal FRR daemon skeleton */ #include #include "libfrr.h" #include "frrevent.h" #include "command.h" #include "vty.h" #include "log.h" static struct event_loop *master; /* Command definitions */ DEFUN(show_example, show_example_cmd, "show example", SHOW_STR "Example information\n") { vty_out(vty, "Example daemon is running\n"); return CMD_SUCCESS; } /* Configuration write callback */ static int config_write(struct vty *vty) { /* Write daemon-specific configuration */ return 0; } /* Daemon initialization */ static void daemon_init(void) { /* Install commands */ install_element(VIEW_NODE, &show_example_cmd); /* Register configuration callback */ install_node(&my_node); install_default(MY_NODE); } /* FRR daemon options */ static struct frr_daemon_info daemon_info = { .vty_port = 2650, .progname = "exampld", .name = "example", .log_name = "EXAMPLE", .version = "1.0", .copyright = "GPL-2.0-or-later", }; /* Main entry point */ int main(int argc, char **argv) { struct frr_signal_t signals[] = { {.signal = SIGUSR1, .handler = sigusr1_handler}, {.signal = SIGINT, .handler = sigint_handler}, {.signal = SIGTERM, .handler = sigterm_handler}, }; frr_preinit(&daemon_info, argc, argv); frr_opt_add("", NULL, NULL); /* Parse command line options */ while (1) { int opt = frr_getopt(argc, argv, NULL); if (opt == EOF) break; } master = frr_init(); daemon_init(); /* Start event loop */ frr_config_fork(); frr_run(master); /* Cleanup */ frr_fini(); return 0; } ``` ## Northbound Configuration Interface YANG-based configuration management The northbound interface provides a modern configuration architecture using YANG data models. It enables transactional configuration changes, configuration validation, and support for management protocols like NETCONF and RESTCONF through mgmtd. ```c /* Define YANG-backed configuration */ #include "northbound.h" #include "northbound_cli.h" /* YANG XPath callbacks */ static int config_create(struct nb_cb_create_args *args) { switch (args->event) { case NB_EV_VALIDATE: /* Validate configuration */ if (!validate_config(args)) return NB_ERR_VALIDATION; break; case NB_EV_PREPARE: /* Allocate resources */ args->resource->ptr = allocate_resource(); break; case NB_EV_APPLY: /* Apply configuration */ apply_config(args); break; case NB_EV_ABORT: /* Rollback on failure */ free_resource(args->resource->ptr); break; } return NB_OK; } static int config_destroy(struct nb_cb_destroy_args *args) { if (args->event != NB_EV_APPLY) return NB_OK; destroy_config(args); return NB_OK; } static int config_modify(struct nb_cb_modify_args *args) { if (args->event != NB_EV_APPLY) return NB_OK; const char *value = yang_dnode_get_string(args->dnode, NULL); modify_config(args->resource->ptr, value); return NB_OK; } /* Register northbound callbacks */ const struct frr_yang_module_info my_yang_module_info = { .name = "frr-example", .nodes = { { .xpath = "/frr-example:example/config", .cbs.create = config_create, .cbs.destroy = config_destroy, .cbs.modify = config_modify, }, {.xpath = NULL}, } }; /* Access configuration via candidate/running datastores */ void example_config_transaction(void) { struct nb_config *candidate; struct lyd_node *dnode; char xpath[XPATH_MAXLEN]; /* Start configuration transaction */ candidate = nb_config_dup(running_config); /* Modify configuration */ snprintf(xpath, sizeof(xpath), "/frr-example:example/interface[name='eth0']/enabled"); nb_candidate_edit(candidate, xpath, NULL, "true"); /* Commit with validation */ nb_candidate_commit(candidate, NB_CLIENT_CLI, NULL, NULL); } ``` ## Use Cases and Integration FRRouting serves as the routing platform for diverse networking scenarios. In data center environments, FRR powers leaf-spine architectures with BGP EVPN overlays, providing L2/L3 VPN services with VXLAN encapsulation. Service providers deploy FRR for edge routing, MPLS networks, and internet peering, taking advantage of its BGP scalability and policy flexibility. Enterprise networks use FRR for redundant WAN edge deployments with protocols like OSPF for internal routing and BGP for multi-homing to ISPs. Cloud platforms integrate FRR into virtual routers and network appliances, leveraging its VRF support for tenant isolation and its API-friendly architecture for automation. The software integrates seamlessly with network automation tools through multiple interfaces. Configuration can be managed programmatically via the vtysh command-line interface, YANG/NETCONF through mgmtd, or by directly editing configuration files. The modular daemon architecture allows selective deployment of only needed protocols, reducing resource footprint. FRR's compatibility with Linux kernel networking features like network namespaces, VRF, MPLS, and eBPF enables sophisticated network function virtualization. Container orchestration platforms can run FRR daemons as sidecars or DaemonSets, providing dynamic routing for Kubernetes, Docker Swarm, or OpenStack deployments. Monitoring and observability are supported through SNMP, syslog, systemd integration, and built-in JSON output for most show commands, facilitating integration with tools like Prometheus, Grafana, and ELK stack.