VyOSXXIII · BGP FundamentalsBGP
BGP RIB and FRR table architecture
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
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:
bgpdowns BGP sessions, path attributes, policy, and table selection.zebrareceives 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:
| Evidence | Meaning | Next question |
|---|---|---|
| Session not Established | TCP or BGP negotiation failed | Is the peer reachable and configured? |
| No Adj-RIBs-In path | Peer did not advertise or the address family is wrong | What does the detailed neighbor output show? |
| Adj-RIBs-In present, Loc-RIB absent | Inbound policy or candidate validation rejected it | Which filter or attribute changed? |
| Loc-RIB present, FIB absent | Selection happened, installation did not | Is NEXT_HOP reachable and permitted? |
| Loc-RIB present, Adj-RIBs-Out absent | No eligible advertisement to that peer | What does the outbound policy say? |
| FIB present | Packet forwarding path exists | Does 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 routeand missing an inbound filter that removed a route before best-path selection; - looking only at
show bgp summaryand 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
Q1. Which BGP table contains the selected best paths before a route is sent to zebra for kernel installation?
Q2. A route in the Loc-RIB is guaranteed to be installed in the Linux kernel FIB and advertised to every eBGP peer.
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.
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.