Skip to main content
RunBook Academy

VyOSXXIII · BGP FundamentalsBGP

BGP RIB and FRR table architecture

Advanced⏱ ~25 minshow bgp summaryshow bgp ipv4 unicastshow bgp neighborshow ip routeshow ip route bgpvtyshrun show configuration

What you'll learn

  • Define Adj-RIBs-In, Loc-RIB, and Adj-RIBs-Out
  • Explain how FRR bgpd applies inbound and outbound policy
  • Trace a selected BGP path into the Linux kernel FIB through zebra
  • Diagnose why a route exists in one BGP table but not another

Prerequisites

Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15

Not yet marked complete on this device.

BGP RIB and FRR table architecture

A BGP route can exist in one table and not another. That is not a contradiction; it is the normal consequence of BGP maintaining several RIB views for different jobs. The three names that matter most are Adj-RIBs-In, Loc-RIB, and Adj-RIBs-Out.

The model is the control-plane equivalent of a warehouse with three doors: inbound receiving, local decision, and outbound shipping. A parcel can be accepted at the receiving door, rejected by inventory, selected for local use, or withheld from a particular truck. The operator who only watches the final forwarding table misses the exact decision that failed.

flowchart LR
  U["Peer UPDATE"] --> A["Adj-RIBs-In<br/>received candidates"]
  A --> I["Inbound policy"]
  I --> S["Best-path selection"]
  S --> L["Loc-RIB<br/>selected best paths"]
  L --> Z["zebra / kernel FIB"]
  L --> O["Outbound policy"]
  O --> B["Adj-RIBs-Out<br/>neighbor-specific"]
  B --> E["Encoded UPDATE"]

Adj-RIBs-In: received candidates

An Adj-RIBs-In is the per-peer, per-address-family collection of routes received from a neighbor before the local policy decision is complete. In a router with many peers, there is not one physical global inbox: FRR maintains the relevant view for each peer and AFI/SAFI.

This table answers “what did this neighbor send me?” It is the first place to look after a session reaches Established when the operator suspects that a route is missing. A route absent from Adj-RIBs-In was not sent, was filtered before FRR retained it, or belongs to an address family that is not active.

The received view is not the local best path. It can contain several paths to the same prefix from one neighbor and it can contain a route that the outbound policy will later remove.

Loc-RIB: the local decision

The Loc-RIB contains the selected best path for each destination and address family after inbound policy and the BGP decision process have run. A route in the Loc-RIB is the answer to “which path will this router use and advertise onward according to local policy?”

Best path is a per-router decision. Another router in the same AS can select a different path because its neighbor set, IGP cost, router ID, or policy differs. That is why a correct Loc-RIB on one edge does not prove that every internal router sees the same selected path.

The Loc-RIB is also not the Linux FIB. A selected route can still be withheld from the kernel by an unusable next hop, an administrative distance decision, or a local policy that prevents installation.

Adj-RIBs-Out: the outbound view

Adj-RIBs-Out is the per-neighbor, per-address-family view of routes that are eligible to be advertised after local selection and outbound policy. The actual view can differ from a route map authored on paper because:

  • the peer is in a different VRF or address family;
  • a prefix-list or route-map denies the route;
  • NEXT_HOP is rewritten for eBGP;
  • the route is suppressed, aggregated, or conditionally advertised;
  • the neighbor has a maximum outbound prefix limit;
  • the path is not installed in the FIB and the policy requires that condition.

A route absent from Adj-RIBs-Out is not necessarily absent from the Loc-RIB. It may simply not be allowed to leave toward that particular peer.

The FRR handoff

FRR separates the jobs across daemons:

  • bgpd owns BGP sessions, path attributes, policy, and table selection.
  • zebra receives route decisions and communicates with the Linux kernel through its routing-table abstraction.
  • the kernel FIB holds the paths that actually participate in packet forwarding, subject to administrative distance and next-hop resolution.
  • the data plane does not inspect AS_PATH for every packet; it uses the installed route and next hop.

The production query ladder

Use commands from the outside in, starting with the symptom:

show bgp summary
show bgp neighbor 192.0.2.2
show bgp ipv4 unicast 198.51.100.0/24
show ip route 198.51.100.0/24
show ip route bgp 198.51.100.0/24

Interpret the result in layers:

EvidenceMeaningNext question
Session not EstablishedTCP or BGP negotiation failedIs the peer reachable and configured?
No Adj-RIBs-In pathPeer did not advertise or the address family is wrongWhat does the detailed neighbor output show?
Adj-RIBs-In present, Loc-RIB absentInbound policy or candidate validation rejected itWhich filter or attribute changed?
Loc-RIB present, FIB absentSelection happened, installation did notIs NEXT_HOP reachable and permitted?
Loc-RIB present, Adj-RIBs-Out absentNo eligible advertisement to that peerWhat does the outbound policy say?
FIB presentPacket forwarding path existsDoes the return path and policy agree?

For a fast candidate view, show bgp ipv4 unicast json may be available on the FRR/VyOS build. Use the text form for an incident note and the JSON form for automation. Record the address family and VRF every time.

How it fails

Common table-boundary mistakes include:

  • looking only at show ip route and missing an inbound filter that removed a route before best-path selection;
  • looking only at show bgp summary and missing an outbound route map that suppresses a selected prefix;
  • assuming a route in the Loc-RIB is usable when its NEXT_HOP is unresolved;
  • applying a policy to the global table when the BGP session is in a VRF;
  • treating a route learned in IPv4 unicast as evidence that the IPv6 unicast family is active;
  • clearing a session before capturing the Adj-RIBs-Out and FIB state needed to explain a flap.

Rollback and safe observation

A table-layer diagnosis is safest when the operator uses soft operations where possible. A route-policy change can often be observed without resetting every peer:

run show bgp neighbor 192.0.2.2
run show bgp ipv4 unicast 198.51.100.0/24
run show ip route 198.51.100.0/24

For a bad outbound policy, remove the neighbor reference. For a bad inbound policy, restore the previous route map or prefix list. If the change must be rolled back across several commits, use the last known good revision and verify the table layers again.

A four-view worksheet

Use the same worksheet for every BGP change. It is deliberately small enough to fit in an incident note:

Neighbor and address family:
Session state before:
Session state after:
Adj-RIBs-In count:
Loc-RIB path and attributes:
Adj-RIBs-Out per neighbor:
FIB next hop and metric:
Inbound policy:
Outbound policy:
Rollback revision:

The worksheet is useful because a route can pass one view and fail another. For example, a prefix can be in Adj-RIBs-In but rejected by inbound policy, selected in the Loc-RIB but withheld from a provider by outbound policy, or installed locally while the return route is missing. The worksheet names the failing boundary before a reset is requested.

When a prefix is changed, compare the before and after snapshots rather than reading a single table in isolation. Record the BGP router ID, selected path, next hop, and update time. That evidence separates a slow advertisement from a route that was never accepted, and it gives the on-call engineer a defensible rollback point.

After a soft refresh, write the new values beside the old ones. The operator should be able to answer not only “does the route exist?” but also “which table changed, which policy caused it, and what can the data plane forward now?”

Cross-course references

XXVI-VyOS-BGPAttributes supplies the attributes that bgpd compares while building the Loc-RIB. XXVII-VyOS-BGPBestPath explains why the selected path differs between routers. XXVIII-VyOS-BGPPrefixFilters and XXXIII-VyOS-RoutePolicy show how inbound and outbound policy alter the table contents. XXXI-VyOS-BGPTroubleshoot turns the four-view method into an evidence-first incident workflow. The Linux course covers the kernel routing table beneath zebra.

Quiz

Knowledge check · 4 questions

  1. Q1. Which BGP table contains the selected best paths before a route is sent to zebra for kernel installation?

  2. Q2. A route in the Loc-RIB is guaranteed to be installed in the Linux kernel FIB and advertised to every eBGP peer.

  3. Q3. A route is present in Adj-RIBs-In, absent from the Loc-RIB, and the session is Established. What is the most likely layer at fault?

    The peer has sent the prefix, so transport and the peer advertisement exist. The local router does not select the candidate. The operator should inspect inbound route policy, malformed attributes, and the first best-path criteria before touching the neighbor session.

  4. Q4. A prefix is selected in the Loc-RIB and installed in the FIB, but a downstream provider says it never received the prefix. What should the operator compare?

    The prefix is usable on the local router, but the downstream provider has a different address family, VRF, outbound policy, or maximum-prefix condition. The operator must compare the neighbor-specific Adj-RIBs-Out with the provider summary rather than assume the global FIB is shared.

Passing score: 75%. Answers are checked in this browser.