-
Notifications
You must be signed in to change notification settings - Fork 458
Route Refresh
BGP Route Refresh allows BGP speakers to request re-advertisement of routes from a peer without tearing down the BGP session. ExaBGP provides full RFC 2918 and RFC 7313 support, enabling soft reconfiguration and enhanced route refresh for dynamic policy changes and operational flexibility.
- What is Route Refresh?
- How Route Refresh Works
- ExaBGP Route Refresh Capabilities
- Route Refresh vs Soft Reconfiguration
- Configuration
- API Usage
- Enhanced Route Refresh (RFC 7313)
- Use Cases
- Monitoring and Verification
- Common Errors and Solutions
- See Also
- References
Route Refresh is a BGP capability defined in RFC 2918 that enables a BGP speaker to request a peer to resend all routes for a specific address family without closing and re-establishing the BGP session.
Before Route Refresh, applying new routing policies required:
- Soft reconfiguration inbound: Store duplicate copy of all received routes (memory intensive)
- Hard reset: Tear down BGP session and re-establish (service disruption)
Result: Either high memory usage or service interruption for policy changes.
With Route Refresh capability:
- Change routing policy (import filters, route-maps, etc.)
- Send Route Refresh request to peer
- Peer re-sends all routes for requested address family
- Apply new policy to refreshed routes
- No session disruption, no duplicate storage
Result: Dynamic policy changes without downtime or memory overhead.
[Policy Change with Route Refresh]
ExaBGP BGP Peer
β β
β BGP session established β
β Route Refresh capability negotiated β
β β
β Operator changes import policy β
β (e.g., filter routes from AS 64512) β
β β
βββββ Route Refresh Request βββββββββββββΆβ
β AFI: IPv4 (1) β
β SAFI: Unicast (1) β
β β
β Peer re-sends
β all IPv4 routes
β β
ββββββ UPDATE (route 1) ββββββββββββββββββ
ββββββ UPDATE (route 2) ββββββββββββββββββ
ββββββ UPDATE (route 3) ββββββββββββββββββ
ββββββ ... ββββββββββββββββββββββββββββββββ
ββββββ END-OF-RIB βββββββββββββββββββββββββ
β β
β Apply new policy to all routes β
β Filtered routes not installed β
β β
β Policy change complete - NO SESSION β
β DISRUPTION! β
Key Points:
- Request specifies AFI/SAFI (address family)
- Peer re-advertises ALL routes for that family
- Session remains established
- Minimal disruption (just route processing)
ExaBGP provides full Route Refresh implementation:
β Route Refresh Capability (RFC 2918):
- Request route refresh for any address family
- Support as both sender and receiver
- Per-AFI/SAFI refresh requests
β Enhanced Route Refresh (RFC 7313):
- BoRR (Beginning-of-Route-Refresh) marker
- EoRR (End-of-Route-Refresh) marker
- Demarcate refresh operation boundaries
β All Address Families:
- IPv4/IPv6 Unicast
- IPv4/IPv6 Multicast
- VPNv4/VPNv6
- FlowSpec (IPv4/IPv6)
- EVPN
- BGP-LS
- All supported AFI/SAFI combinations
β API Integration:
- Trigger route refresh via API commands
- Receive route refresh requests from peers
- JSON and text format support
Implementation: src/exabgp/bgp/message/refresh.py
RFC Compliance:
- RFC 2918: Route Refresh Capability for BGP-4
- RFC 7313: Enhanced Route Refresh Capability for BGP-4
| Feature | Route Refresh | Soft Reconfiguration Inbound |
|---|---|---|
| Memory Usage | Normal (single RIB) | High (duplicate routes stored) |
| Session Impact | None | None |
| RFC | RFC 2918 | Pre-RFC mechanism |
| Peer Support Required | Yes (capability) | No |
| Performance | Re-transmission overhead | Instant (stored routes) |
| Recommended | β Yes (modern) | β No (legacy) |
β Use Route Refresh when:
- Peer supports Route Refresh capability (most modern BGP implementations)
- Memory is constrained
- Moderate route refresh frequency
- Standard deployment
β Avoid Route Refresh when:
- Extremely frequent policy changes (multiple times per minute)
- Peer does not support Route Refresh capability
- Memory is abundant and instant policy application required
Recommendation: Always prefer Route Refresh over soft reconfiguration inbound. It's the modern, standard approach.
Basic configuration:
neighbor 192.168.1.1 {
router-id 192.168.1.2;
local-address 192.168.1.2;
local-as 65001;
peer-as 65000;
capability {
route-refresh; # Enable route refresh capability
}
family {
ipv4 unicast;
ipv6 unicast;
}
api {
processes [ policy-manager ];
}
}
process policy-manager {
run python3 /etc/exabgp/api/refresh.py;
encoder text;
}Notes:
-
route-refreshis typically enabled by default in modern ExaBGP versions - Explicit configuration ensures capability is advertised
- Capability must be negotiated during session establishment
Disable Route Refresh (rare):
neighbor 192.168.1.1 {
# ... neighbor config ...
capability {
route-refresh disable; # Explicitly disable
}
}When to disable:
- Testing legacy BGP behavior
- Peer incompatibility (very rare)
- Debugging route refresh issues
Trigger route refresh via API:
#!/usr/bin/env python3
import sys
def request_refresh():
"""Request IPv4 unicast route refresh"""
sys.stdout.write("announce route-refresh ipv4 unicast\n")
sys.stdout.flush()
def request_ipv6_refresh():
"""Request IPv6 unicast route refresh"""
sys.stdout.write("announce route-refresh ipv6 unicast\n")
sys.stdout.flush()
def request_flowspec_refresh():
"""Request IPv4 FlowSpec route refresh"""
sys.stdout.write("announce route-refresh ipv4 flow\n")
sys.stdout.flush()
# Trigger refresh after policy change
request_refresh()Syntax:
announce route-refresh <afi> <safi>
Examples:
announce route-refresh ipv4 unicast
announce route-refresh ipv6 unicast
announce route-refresh ipv4 multicast
announce route-refresh ipv4 vpn
announce route-refresh ipv4 flow
announce route-refresh evpn
announce route-refresh bgplsJSON API format:
#!/usr/bin/env python3
import sys
import json
def request_refresh_json():
"""Request route refresh using JSON API"""
command = {
"exabgp": "5.0",
"time": 1699564800.0,
"neighbor": "192.168.1.1",
"message": {
"refresh": {
"afi": "ipv4",
"safi": "unicast"
}
}
}
sys.stdout.write(json.dumps(command) + "\n")
sys.stdout.flush()
request_refresh_json()Handle incoming refresh requests:
#!/usr/bin/env python3
import sys
import json
# Configure process for JSON
# encoder = json
while True:
line = sys.stdin.readline().strip()
if not line:
break
try:
msg = json.loads(line)
# Detect route refresh request from peer
if msg.get('type') == 'refresh':
afi = msg['refresh']['afi']
safi = msg['refresh']['safi']
print(f"Peer requested refresh: {afi}/{safi}", file=sys.stderr)
# Re-announce all routes for this AFI/SAFI
if afi == 'ipv4' and safi == 'unicast':
re_announce_ipv4_routes()
except json.JSONDecodeError:
pass
def re_announce_ipv4_routes():
"""Re-announce all IPv4 routes after refresh request"""
routes = [
"announce route 10.0.0.0/8 next-hop 192.168.1.2",
"announce route 172.16.0.0/12 next-hop 192.168.1.2",
"announce route 192.168.0.0/16 next-hop 192.168.1.2",
]
for route in routes:
sys.stdout.write(f"{route}\n")
sys.stdout.flush()RFC 7313 defines Enhanced Route Refresh with BoRR (Beginning-of-Route-Refresh) and EoRR (End-of-Route-Refresh) markers to clearly demarcate refresh operations.
- Clear Boundaries: Know when refresh starts and ends
- Concurrent Refresh: Support multiple simultaneous refresh operations
- Debugging: Easier troubleshooting of refresh operations
- Stale Route Detection: Identify routes not refreshed
ExaBGP BGP Peer
β β
βββββ Enhanced Route Refresh Request ββββΆβ
β AFI: IPv4, SAFI: Unicast β
β Subtype: BoRR (1) β
β β
ββββββ BoRR Marker βββββββββββββββββββββββ
β (Beginning-of-Route-Refresh) β
β β
ββββββ UPDATE (route 1) ββββββββββββββββββ
ββββββ UPDATE (route 2) ββββββββββββββββββ
ββββββ UPDATE (route 3) ββββββββββββββββββ
ββββββ ... ββββββββββββββββββββββββββββββββ
β β
ββββββ EoRR Marker βββββββββββββββββββββββ
β (End-of-Route-Refresh) β
β β
β All routes between BoRR and EoRR β
β are part of refresh operation β
BoRR/EoRR Subtypes:
- 0: Normal Route Refresh (RFC 2918)
- 1: BoRR (Beginning-of-Route-Refresh)
- 2: EoRR (End-of-Route-Refresh)
ExaBGP Support: Fully implemented in src/exabgp/bgp/message/refresh.py
Scenario: Change BGP import policy without session disruption.
Example:
#!/usr/bin/env python3
"""Dynamic BGP policy manager with route refresh"""
import sys
import time
def apply_new_policy():
"""Apply new import policy and refresh routes"""
# Step 1: Update policy (e.g., filter specific AS)
print("Applying new import policy: block AS 64512", file=sys.stderr)
# Step 2: Request route refresh to apply new policy
sys.stdout.write("announce route-refresh ipv4 unicast\n")
sys.stdout.flush()
print("Route refresh requested - policy will apply to refreshed routes", file=sys.stderr)
# Trigger policy change
apply_new_policy()Benefits:
- No BGP session reset
- No traffic disruption
- Immediate policy enforcement
Scenario: Re-evaluate routes after an external system event (health check, monitoring alert).
Example:
#!/usr/bin/env python3
"""Health check integration with route refresh"""
import sys
import requests
def check_backend_health():
"""Check if backend service is healthy"""
try:
response = requests.get("http://localhost:8080/health", timeout=2)
return response.status_code == 200
except:
return False
def refresh_on_health_change(was_healthy):
"""Refresh routes if health status changed"""
is_healthy = check_backend_health()
if is_healthy != was_healthy:
print(f"Health changed: {was_healthy} -> {is_healthy}", file=sys.stderr)
# Request route refresh to re-evaluate announcements
sys.stdout.write("announce route-refresh ipv4 unicast\n")
sys.stdout.flush()
return is_healthy
# Monitor health and refresh on change
healthy = check_backend_health()
while True:
time.sleep(10)
healthy = refresh_on_health_change(healthy)Scenario: Update FlowSpec filtering rules dynamically.
Example:
#!/usr/bin/env python3
"""FlowSpec DDoS mitigation with route refresh"""
import sys
def update_ddos_filters():
"""Update FlowSpec filters and refresh"""
# Announce new FlowSpec rule
flowspec = (
"announce flow route "
"{ match { source 1.2.3.4/32; destination-port =80; protocol tcp; } "
"then { rate-limit 0; } }"
)
sys.stdout.write(f"{flowspec}\n")
sys.stdout.flush()
# Request route refresh to ensure rules are synchronized
sys.stdout.write("announce route-refresh ipv4 flow\n")
sys.stdout.flush()
print("FlowSpec filters updated and refresh requested", file=sys.stderr)
update_ddos_filters()Scenario: Route Reflector client requests refresh after policy change.
Configuration:
neighbor 192.168.1.254 { # Route Reflector
router-id 192.168.1.2;
local-address 192.168.1.2;
local-as 65001;
peer-as 65001; # iBGP
capability {
route-refresh;
}
family {
ipv4 unicast;
ipv6 unicast;
vpnv4;
}
api {
processes [ rr-client ];
}
}API usage:
#!/usr/bin/env python3
"""Route Reflector client route refresh"""
import sys
def refresh_from_rr():
"""Request full route refresh from Route Reflector"""
families = [
"ipv4 unicast",
"ipv6 unicast",
"ipv4 vpn",
]
for family in families:
sys.stdout.write(f"announce route-refresh {family}\n")
sys.stdout.flush()
print("Requested route refresh from RR for all families", file=sys.stderr)
refresh_from_rr()Monitor route refresh events:
#!/usr/bin/env python3
"""Monitor route refresh events via API"""
import sys
import json
while True:
line = sys.stdin.readline().strip()
if not line:
break
try:
msg = json.loads(line)
# Incoming route refresh request from peer
if msg.get('type') == 'refresh':
print(f"REFRESH REQUEST: {msg}", file=sys.stderr)
# BoRR marker (Enhanced Route Refresh)
if msg.get('type') == 'refresh' and msg.get('subtype') == 'bor':
print(f"BoRR: Route refresh starting for {msg['afi']}/{msg['safi']}", file=sys.stderr)
# EoRR marker (Enhanced Route Refresh)
if msg.get('type') == 'refresh' and msg.get('subtype') == 'eor':
print(f"EoRR: Route refresh complete for {msg['afi']}/{msg['safi']}", file=sys.stderr)
except json.JSONDecodeError:
passEnable route refresh logging:
[exabgp.log]
level = INFO
packets = true
message = trueLog output:
INFO Peer 192.168.1.1: Received ROUTE-REFRESH for ipv4/unicast
INFO Peer 192.168.1.1: Sending ROUTE-REFRESH for ipv4/unicast
INFO Peer 192.168.1.1: Enhanced Route Refresh BoRR received
INFO Peer 192.168.1.1: Enhanced Route Refresh EoRR received
Verify Route Refresh capability:
# Check capability negotiation in logs
grep -i "route-refresh" /var/log/exabgp.log
# Verify capability in OPEN message
# Enable packet logging
[exabgp.log]
packets = true
level = DEBUGTest route refresh:
#!/usr/bin/env python3
"""Test route refresh functionality"""
import sys
import time
# Request refresh
sys.stdout.write("announce route-refresh ipv4 unicast\n")
sys.stdout.flush()
print("Route refresh requested - check logs for UPDATE messages", file=sys.stderr)Symptom: Route refresh request fails or ignored.
Logs:
WARNING Peer 192.168.1.1: Route Refresh capability not negotiated
ERROR Cannot send route refresh - capability not available
Causes:
- Peer does not support Route Refresh (RFC 2918)
- Capability not negotiated during OPEN
- ExaBGP capability disabled
Solutions:
# Ensure capability enabled in ExaBGP
neighbor 192.168.1.1 {
capability {
route-refresh; # Enable explicitly
}
}
# Verify peer configuration
# Cisco (should be default):
router bgp 65000
neighbor 192.168.1.2 activate
# Check OPEN message for capability advertisement
# Capability Code: 2 (Route Refresh)Symptom: Route refresh for specific address family fails.
Logs:
ERROR Route refresh failed: ipv6/unicast not negotiated
Causes:
- Address family not configured in
familyblock - Peer does not support requested AFI/SAFI
- Typo in AFI/SAFI name
Solutions:
# Ensure address family configured
neighbor 192.168.1.1 {
family {
ipv4 unicast; # Must be configured
ipv6 unicast; # Must be configured
}
capability {
route-refresh;
}
}
# Verify API command syntax
# Correct:
announce route-refresh ipv4 unicast
announce route-refresh ipv6 unicast
# Incorrect:
announce route-refresh ipv4 # Missing SAFI
announce route-refresh ipv6-unicast # Wrong formatSymptom: Route refresh request sent but no UPDATE messages received.
Causes:
- Peer has no routes to advertise
- All routes filtered by peer's export policy
- Refresh request not received by peer
Solutions:
# Verify peer has routes
# Cisco:
show bgp ipv4 unicast neighbors 192.168.1.2 advertised-routes
# Juniper:
show route advertising-protocol bgp 192.168.1.2
# Check ExaBGP logs for UPDATE messages
tail -f /var/log/exabgp.log | grep UPDATE
# Enable debug logging
[exabgp.log]
level = DEBUG
packets = true
message = trueSymptom: Too many route refresh requests causing instability.
Logs:
WARNING Peer 192.168.1.1: Route refresh requested 10 times in 60 seconds
Causes:
- API process bug (refresh loop)
- Misconfigured automation
- Policy flapping
Solutions:
#!/usr/bin/env python3
"""Rate-limited route refresh"""
import sys
import time
class RateLimitedRefresh:
def __init__(self, min_interval=60):
self.min_interval = min_interval
self.last_refresh = 0
def request_refresh(self, afi, safi):
"""Request refresh with rate limiting"""
now = time.time()
if now - self.last_refresh < self.min_interval:
remaining = self.min_interval - (now - self.last_refresh)
print(f"Rate limit: wait {remaining:.0f}s before next refresh", file=sys.stderr)
return False
sys.stdout.write(f"announce route-refresh {afi} {safi}\n")
sys.stdout.flush()
self.last_refresh = now
return True
# Use rate limiter
refresher = RateLimitedRefresh(min_interval=60)
refresher.request_refresh("ipv4", "unicast")- Graceful Restart - Graceful restart capability
- API Commands - All API commands including route-refresh
- Configuration Syntax - Complete configuration reference
- API Overview - API architecture and integration
- RFC 2918: Route Refresh Capability for BGP-4
- RFC 7313: Enhanced Route Refresh Capability for BGP-4
- RFC 4271: BGP-4 base specification
- RFC Support - All implemented RFCs
- RFC Information - Detailed RFC implementation list
-
Source Code:
src/exabgp/bgp/message/refresh.py - Capability Type: 2 (Route Refresh)
- Enhanced Capability Type: 70 (Enhanced Route Refresh)
- ExaBGP Version: 3.x, 4.x, 5.x/main
π» Ghost written by Claude (Anthropic AI)
π Home
π Getting Started
π§ API
π‘οΈ Use Cases
π Address Families
βοΈ Configuration
π Operations
π Reference
- Architecture
- BGP State Machine
- Communities (RFC)
- Extended Communities
- BGP Ecosystem
- Capabilities (AFI/SAFI)
- RFC Support
π Migration
π Community
π External
- GitHub Repo β
- Slack β
- Issues β
π» Ghost written by Claude (Anthropic AI)