-
Notifications
You must be signed in to change notification settings - Fork 460
API Commands
A-Z alphabetical reference for all ExaBGP API commands
π For detailed examples and patterns, see Text API Reference and JSON API Reference
- Command Format
- Neighbor Selectors (Targeting Specific Peers)
- Announce Commands
- Withdraw Commands
- Operational Commands
- Control Commands
- Quick Reference Table
- Command Acknowledgment (ACK)
- Common Errors
All API commands are sent to ExaBGP via STDOUT from your process.
Basic pattern:
import sys
# Send command
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
sys.stdout.flush() # CRITICAL: Always flush!Important:
- β
Always end commands with
\n - β
Always call
sys.stdout.flush()after writing - β Commands are case-sensitive
- β
ExaBGP 4.x and 5.0.0+ send ACK responses by default (
done/error/shutdown) - βΉοΈ ACK can be disabled:
- Environment variable:
exabgp.api.ack=false(4.x and 5.0.0+) - Runtime commands:
disable-ackorsilence-ack(5.0.0+ only)
- Environment variable:
When you have multiple BGP peers configured with the same API process, you can use neighbor selectors to target specific peers with your announce/withdraw commands.
neighbor <ip> [<selector-options>] <command>
By default, commands apply to all configured neighbors (equivalent to neighbor *). Use the neighbor keyword when you want to target specific peer(s) instead of broadcasting to all neighbors.
Use these optional filters to differentiate between multiple peers with the same IP or to target groups of peers:
| Selector | Purpose | Example |
|---|---|---|
neighbor <ip> |
Required: Target specific neighbor by IP | neighbor 127.0.0.1 |
local-ip <ip> |
Filter by local IP address | local-ip 192.168.1.2 |
local-as <asn> |
Filter by local ASN | local-as 65001 |
peer-as <asn> |
Filter by peer ASN | peer-as 65000 |
router-id <id> |
Filter by router ID | router-id 192.168.1.1 |
family-allowed <families> |
Filter by address family capabilities | family-allowed ipv4-unicast/ipv6-unicast |
Multiple neighbors (comma-separated):
# Target multiple specific neighbors
neighbor 127.0.0.1,192.168.1.1 announce route 10.0.0.0/24 next-hop selfWildcard (all neighbors):
# Target ALL configured neighbors
neighbor * announce route 10.0.0.0/24 next-hop selfSimple single neighbor:
# Announce to specific neighbor
sys.stdout.write("neighbor 127.0.0.1 announce route 10.0.0.0/24 next-hop 192.168.1.1\n")
sys.stdout.flush()Target all neighbors:
# Announce to all neighbors
sys.stdout.write("neighbor * announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()Multiple neighbors:
# Announce to two specific neighbors
sys.stdout.write("neighbor 10.0.0.1,10.0.0.2 announce route 100.10.0.0/24 next-hop self\n")
sys.stdout.flush()Differentiate by local ASN:
# If you have multiple neighbors at same IP but different local-as
sys.stdout.write("neighbor 127.0.0.1 local-as 65000 announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()Differentiate by peer ASN:
# Target specific peer-as
sys.stdout.write("neighbor 127.0.0.1 peer-as 65001 announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()Multiple selectors:
# Combine multiple selectors for precise targeting
sys.stdout.write("neighbor 127.0.0.1 local-as 65000 peer-as 65001 announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()Filter by address family:
# Target neighbors that support IPv4 unicast
sys.stdout.write("neighbor * family-allowed ipv4-unicast announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()
# Target neighbors supporting both IPv4 and IPv6 unicast (multi-session)
sys.stdout.write("neighbor * family-allowed ipv4-unicast/ipv6-unicast announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()
# Target neighbors with FlowSpec capability
sys.stdout.write("neighbor * family-allowed ipv4-flowspec announce flow route { match { destination 10.0.0.0/8; } then { discard; } }\n")
sys.stdout.flush()#!/usr/bin/env python3
"""
multi_peer_announce.py - Announce different routes to different peers
"""
import sys
import time
time.sleep(2) # Wait for BGP sessions
# Announce to all neighbors
sys.stdout.write("neighbor * announce route 100.10.0.0/24 next-hop self\n")
sys.stdout.flush()
# Announce specific route to specific neighbor
sys.stdout.write("neighbor 192.168.1.1 announce route 100.20.0.0/24 next-hop self\n")
sys.stdout.flush()
# Announce to multiple neighbors
sys.stdout.write("neighbor 192.168.1.1,192.168.1.2 announce route 100.30.0.0/24 next-hop self\n")
sys.stdout.flush()
# Target by peer AS
sys.stdout.write("neighbor 192.168.1.1 peer-as 65000 announce route 100.40.0.0/24 next-hop self\n")
sys.stdout.flush()
# Keep running
while True:
time.sleep(60)The family-allowed selector filters neighbors based on their negotiated address family capabilities. The value format depends on the neighbor configuration:
Single-session neighbors (default):
- Value:
in-open - All address families are negotiated in the BGP OPEN message
- Example:
family-allowed in-open
Multi-session neighbors (when multi-session capability is enabled):
- Value: Slash-separated list of address families
- Format:
<afi>-<safi>/<afi>-<safi>/... - Example:
family-allowed ipv4-unicast/ipv6-unicast/ipv4-flowspec
Common address family values:
-
ipv4-unicast- IPv4 unicast routes -
ipv6-unicast- IPv6 unicast routes -
ipv4-flowspec- IPv4 FlowSpec rules -
ipv6-flowspec- IPv6 FlowSpec rules -
ipv4-mpls-vpn- IPv4 L3VPN (VPNv4) -
ipv6-mpls-vpn- IPv6 L3VPN (VPNv6) -
l2vpn-evpn- EVPN routes -
ipv4-multicast- IPv4 multicast -
ipv6-multicast- IPv6 multicast
Examples:
# Target only neighbors with FlowSpec capability (multi-session)
sys.stdout.write("neighbor * family-allowed ipv4-flowspec announce flow route { match { destination 10.0.0.0/8; } then { discard; } }\n")
sys.stdout.flush()
# Target neighbors with dual-stack unicast capability
sys.stdout.write("neighbor * family-allowed ipv4-unicast/ipv6-unicast announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()
# Target single-session neighbors (all families negotiated in OPEN)
sys.stdout.write("neighbor * family-allowed in-open announce route 10.0.0.0/24 next-hop self\n")
sys.stdout.flush()Use case: Send FlowSpec rules only to neighbors that support FlowSpec, avoiding errors on neighbors that don't support it.
1. Per-Peer Route Customization:
# Announce different routes to different transit providers
sys.stdout.write("neighbor 10.0.1.1 announce route 100.10.0.0/24 next-hop self as-path [65001 65001]\n") # Provider A
sys.stdout.flush()
sys.stdout.write("neighbor 10.0.2.1 announce route 100.10.0.0/24 next-hop self\n") # Provider B (preferred)
sys.stdout.flush()2. Geographic Load Balancing:
# US datacenter announces to US peers
sys.stdout.write("neighbor 192.168.1.1 announce route 100.10.0.100/32 next-hop self local-preference 200\n")
sys.stdout.flush()
# EU datacenter announces to EU peers
sys.stdout.write("neighbor 192.168.2.1 announce route 100.10.0.100/32 next-hop self local-preference 100\n")
sys.stdout.flush()3. ASN-Based Filtering:
# Only announce to peers in specific AS
sys.stdout.write("neighbor * peer-as 65000 announce route 10.0.0.0/8 next-hop self\n")
sys.stdout.flush()- π‘ Default behavior: Commands without
neighborselector apply to all configured neighbors (equivalent toneighbor *) - π‘ Selective targeting: Use
neighborkeyword to target specific peer(s) instead of all neighbors - π‘ The
neighborselector always comes before the command (announce/withdraw) - π‘ Selectors are evaluated as AND logic - all specified selectors must match
- π‘ If no neighbor matches your selectors, the command is silently ignored
neighbor 192.168.1.1 {
router-id 192.168.1.2;
local-address 192.168.1.2;
local-as 65001;
peer-as 65000;
api {
processes [ my-program ];
}
}
neighbor 192.168.2.1 {
router-id 192.168.1.2;
local-address 192.168.1.2;
local-as 65001;
peer-as 65002;
api {
processes [ my-program ];
}
}
process my-program {
run /etc/exabgp/api/announce.py;
encoder text;
}With this configuration, your API program can selectively target either neighbor using selectors.
Commands to advertise BGP routes.
Announce IPv4/IPv6 unicast route
announce route <prefix> next-hop <ip> [attributes]Examples:
# Basic IPv4
announce route 100.10.0.100/32 next-hop self
# IPv6
announce route 2001:db8::1/128 next-hop 2001:db8::2
# With attributes
announce route 100.10.0.100/32 next-hop self community [65001:100]
announce route 100.10.0.100/32 next-hop self as-path [65001 65002]
announce route 100.10.0.100/32 next-hop self local-preference 200
announce route 100.10.0.100/32 next-hop self med 50Attributes:
-
next-hop self- Use local router IP -
next-hop <ip>- Explicit next-hop -
community [<asn>:<value>]- BGP communities -
as-path [<asn> ...]- AS path -
local-preference <n>- Local preference (higher = preferred) -
med <n>- Multi-Exit Discriminator (lower = preferred) -
origin igp|egp|incomplete- Origin attribute
See also:
Announce FlowSpec rule
announce flow route { match { <conditions> } then { <actions> } }Examples:
# Block TCP port 80 from 10.0.0.0/8
announce flow route { match { source 10.0.0.0/8; destination-port =80; protocol =tcp; } then { discard; } }
# Rate-limit DNS
announce flow route { match { destination-port =53; protocol =udp; } then { rate-limit 1000000; } }
# Block SYN flood
announce flow route { match { destination-port =443; tcp-flags [ syn ]; protocol =tcp; } then { discard; } }
# Redirect to VRF
announce flow route { match { destination 100.10.0.0/24; } then { redirect 65001:100; } }Match conditions:
-
source <prefix>- Source IP -
destination <prefix>- Destination IP -
protocol =<n>- IP protocol (tcp=6, udp=17, icmp=1) -
source-port <op><n>- Source port -
destination-port <op><n>- Destination port -
packet-length <op><n>- Packet length -
tcp-flags [ <flags> ]- TCP flags -
icmp-type =<n>- ICMP type -
icmp-code =<n>- ICMP code -
fragment [ <flags> ]- Fragment flags -
dscp =<n>- DSCP value
Actions:
-
discard- Drop packets -
rate-limit <bytes/sec>- Rate limit -
redirect <rt>- Redirect to VRF -
mark <dscp>- Mark DSCP -
community [ <communities> ]- Tag with community
See also:
Announce L3VPN IPv4 route
announce vpnv4 <prefix> next-hop <ip> route-distinguisher <rd> [attributes]Examples:
# Basic VPNv4
announce vpnv4 10.0.0.0/24 next-hop 192.168.1.2 route-distinguisher 65001:100
# With label and route-target
announce vpnv4 10.0.0.0/24 next-hop 192.168.1.2 route-distinguisher 65001:100 label 16 extended-community [ target:65001:100 ]See also:
Announce L3VPN IPv6 route
announce vpnv6 <prefix> next-hop <ip> route-distinguisher <rd> [attributes]Examples:
announce vpnv6 2001:db8::/32 next-hop 2001:db8::1 route-distinguisher 65001:100
announce vpnv6 2001:db8::/32 next-hop 2001:db8::1 route-distinguisher 65001:100 label 16See also:
Announce EVPN route
EVPN MAC Advertisement:
announce evpn macadvertisement aa:bb:cc:dd:ee:ff 100.10.0.1 1000 rd 65001:100 route-target [ target:65001:100 ]EVPN Multicast:
announce evpn multicast 192.168.1.1 rd 65001:100 route-target [ target:65001:100 ]See also:
Announce VPLS route
announce vpls <endpoint> <offset> <size> rd <rd> route-target [ <rt> ]Example:
announce vpls 192.168.1.1 10 8 rd 65001:100 route-target [ target:65001:100 ]See also:
Request route refresh from peer
announce refresh <afi> <safi>Examples:
# Request IPv4 unicast refresh
announce refresh ipv4 unicast
# Request FlowSpec refresh
announce refresh ipv4 flowspecSee also:
Commands to remove previously announced routes.
Withdraw IPv4/IPv6 unicast route
withdraw route <prefix> next-hop <ip>Examples:
# Withdraw IPv4
withdraw route 100.10.0.100/32 next-hop self
# Withdraw IPv6
withdraw route 2001:db8::1/128 next-hop 2001:db8::2
# Alternative: withdraw by prefix only (if unique)
withdraw route 100.10.0.100/32Important: Withdrawal must match announcement (prefix + next-hop + attributes).
See also:
Withdraw FlowSpec rule
withdraw flow route { match { <conditions> } }Examples:
# Withdraw by exact match
withdraw flow route { match { source 10.0.0.0/8; destination-port =80; protocol =tcp; } }
# Auto-withdraw pattern
import threading
def auto_withdraw(rule, timeout=300):
time.sleep(timeout)
withdraw = rule.replace('announce', 'withdraw').replace('then { discard; }', '')
sys.stdout.write(withdraw + "\n")
sys.stdout.flush()
rule = "announce flow route { match { source 10.0.0.0/8; } then { discard; } }"
sys.stdout.write(rule + "\n")
sys.stdout.flush()
threading.Thread(target=auto_withdraw, args=(rule,)).start()See also:
Withdraw L3VPN IPv4 route
withdraw vpnv4 <prefix> next-hop <ip> route-distinguisher <rd>Example:
withdraw vpnv4 10.0.0.0/24 next-hop 192.168.1.2 route-distinguisher 65001:100Withdraw L3VPN IPv6 route
withdraw vpnv6 <prefix> next-hop <ip> route-distinguisher <rd>Example:
withdraw vpnv6 2001:db8::/32 next-hop 2001:db8::1 route-distinguisher 65001:100Withdraw EVPN route
withdraw evpn macadvertisement aa:bb:cc:dd:ee:ff 100.10.0.1 1000 rd 65001:100Withdraw VPLS route
withdraw vpls 192.168.1.1 10 8 rd 65001:100Commands for BGP session control and monitoring.
Gracefully shutdown ExaBGP
shutdownExample:
import signal
import sys
def signal_handler(sig, frame):
sys.stdout.write("shutdown\n")
sys.stdout.flush()
sys.exit(0)
signal.signal(signal.SIGTERM, signal_handler)Effect:
- Sends BGP NOTIFICATION to all peers
- Closes connections gracefully
- Exits ExaBGP process
Restart BGP connection to peer
restartExample:
# Restart after configuration change
sys.stdout.write("restart\n")
sys.stdout.flush()Effect:
- Closes existing connections
- Re-reads configuration
- Establishes new connections
Reload configuration without restarting
reloadEffect:
- Re-reads configuration file
- Applies changes without dropping sessions (if possible)
Query ExaBGP version
versionResponse (on STDIN):
exabgp 4.2.25
Commands for flow control and debugging.
Flush pending route updates
flushUse case:
# Announce multiple routes, then flush
for prefix in prefixes:
sys.stdout.write(f"announce route {prefix} next-hop self\n")
sys.stdout.write("flush\n")
sys.stdout.flush()Effect: Forces ExaBGP to send pending BGP UPDATEs immediately.
Re-enable ACK responses (ExaBGP 5.0.0+, safe on 4.x)
enable-ackBehavior:
- β ExaBGP 5.0.0+: Sends "done" ACK, re-enables ACK for future commands
β οΈ ExaBGP 4.x: Prints warning but continues (safe, no harm)- β
All future commands will receive ACK responses (
doneorerror)
Use case:
# Re-enable error checking after fire-and-forget mode
sys.stdout.write("enable-ack\n")
sys.stdout.flush()
# Check for "done" response to confirm ACK is re-enabled
# Now all future commands will receive ACKDisable ACK responses gracefully (ExaBGP 5.0.0+, safe on 4.x)
disable-ackBehavior:
- β ExaBGP 5.0.0+: Sends final "done" ACK, then disables future ACKs
β οΈ ExaBGP 4.x: Prints warning but continues (safe, no harm)- β Future commands will NOT receive ACK responses (fire-and-forget mode)
Use cases:
- Transition to high-performance mode
- Best practice for non-ACK-aware programs on ExaBGP 5.0.0+
Example:
# Transition to high-performance mode
sys.stdout.write("disable-ack\n")
sys.stdout.flush()
# Receive final "done" ACK confirming ACK is now disabled
# Future commands are fire-and-forget (no ACK overhead)
for i in range(10000):
prefix = f"10.{i//256}.{i%256}.0/24"
sys.stdout.write(f"announce route {prefix} next-hop self\n")
sys.stdout.flush()
# No ACK expected - maximum performanceDisable ACK responses immediately (ExaBGP 5.0.0+, safe on 4.x)
silence-ackBehavior:
- β ExaBGP 5.0.0+: Does NOT send ACK for this command (immediate silence)
β οΈ ExaBGP 4.x: Prints warning but continues (safe, no harm)- β Future commands will NOT receive ACK responses (fire-and-forget mode)
Use case:
# Maximum performance - skip even the final ACK
sys.stdout.write("silence-ack\n")
sys.stdout.flush()
# No ACK expected for silence-ack itself
# All future commands are fire-and-forget (no ACK overhead)
for i in range(10000):
prefix = f"10.{i//256}.{i%256}.0/24"
sys.stdout.write(f"announce route {prefix} next-hop self\n")
sys.stdout.flush()Comparison:
| Command | Sends ACK for itself? | Future commands ACKed? |
|---|---|---|
enable-ack |
β Yes ("done") | β Yes |
disable-ack |
β Yes (final "done") | β No |
silence-ack |
β No (immediate silence) | β No |
Version compatibility:
- ExaBGP 4.x: Commands are ignored with warning (safe, no harm)
- ExaBGP 5.x/main: ACK can be controlled dynamically with these runtime commands
Best practice for non-ACK-aware programs:
If you're using ExaBGP 5.x/main with API programs that don't handle ACK responses, send disable-ack at startup:
#!/usr/bin/env python3
import sys
import time
# Safe on all ExaBGP versions (5.x disables, 4.x warns but continues)
sys.stdout.write("disable-ack\n")
sys.stdout.flush()
time.sleep(0.1)
# Your legacy code works without modification
while True:
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
sys.stdout.flush()
time.sleep(5)For maximum compatibility across ExaBGP 4.x and 5.x, combine both methods:
# Set environment variable (works on 4.x and 5.x)
export exabgp.api.ack=false
# AND send disable-ack in your program (defense-in-depth)See also:
- API Overview - Dynamic ACK Control
- API Overview - Best Practice: Non-ACK-Aware Programs
- Text API Reference - ACK Control Commands
| Command | Purpose | Example |
|---|---|---|
announce route |
Announce IPv4/IPv6 route | announce route 1.1.1.1/32 next-hop self |
announce flow |
Announce FlowSpec rule | announce flow route { match { ... } then { ... } } |
announce vpnv4 |
Announce L3VPN IPv4 | announce vpnv4 10.0.0.0/24 ... rd 65001:100 |
announce vpnv6 |
Announce L3VPN IPv6 | announce vpnv6 2001:db8::/32 ... rd 65001:100 |
announce evpn |
Announce EVPN route | announce evpn macadvertisement ... |
announce vpls |
Announce VPLS route | announce vpls 192.168.1.1 ... |
announce refresh |
Request route refresh | announce refresh ipv4 unicast |
withdraw route |
Withdraw IPv4/IPv6 route | withdraw route 1.1.1.1/32 |
withdraw flow |
Withdraw FlowSpec rule | withdraw flow route { match { ... } } |
withdraw vpnv4 |
Withdraw L3VPN IPv4 | withdraw vpnv4 10.0.0.0/24 ... rd 65001:100 |
withdraw vpnv6 |
Withdraw L3VPN IPv6 | withdraw vpnv6 2001:db8::/32 ... rd 65001:100 |
withdraw evpn |
Withdraw EVPN route | withdraw evpn macadvertisement ... |
withdraw vpls |
Withdraw VPLS route | withdraw vpls 192.168.1.1 ... |
shutdown |
Gracefully shutdown | shutdown |
restart |
Restart BGP session | restart |
reload |
Reload configuration | reload |
version |
Query version | version |
flush |
Flush pending updates | flush |
enable-ack |
Re-enable ACK responses (5.x/main, safe on 4.x) | enable-ack |
disable-ack |
Disable ACK gracefully (5.x/main, safe on 4.x) | disable-ack |
silence-ack |
Disable ACK immediately (5.x/main, safe on 4.x) | silence-ack |
ExaBGP 4.x and 5.x send command acknowledgments via STDIN (enabled by default).
Response types:
done # Command succeeded
error # Command failed
shutdown # ExaBGP is shutting downRobust pattern with polling loop:
#!/usr/bin/env python3
import sys
import select
import time
def wait_for_ack(expected_count=1, timeout=30):
"""
Wait for ACK responses with polling loop.
ExaBGP may not respond immediately, so we poll with sleep.
Handles both text and JSON encoder formats:
- Text: "done", "error", "shutdown"
- JSON: {"answer": "done|error|shutdown", "message": "..."}
"""
import json
received = 0
start_time = time.time()
while received < expected_count:
if time.time() - start_time >= timeout:
return False
ready, _, _ = select.select([sys.stdin], [], [], 0.1)
if ready:
line = sys.stdin.readline().strip()
# Parse response (could be text or JSON)
answer = None
if line.startswith('{'):
try:
data = json.loads(line)
answer = data.get('answer')
except:
pass
else:
answer = line
if answer == "done":
received += 1
elif answer == "error":
return False
elif answer == "shutdown":
raise SystemExit(0)
else:
time.sleep(0.1)
return True
def send_command(command):
"""Send command and wait for ACK"""
sys.stdout.write(command + "\n")
sys.stdout.flush()
return wait_for_ack(expected_count=1)
# Use it
send_command("announce route 100.10.0.100/32 next-hop self")Configuration:
[exabgp.api]
ack = true # Default in 5.x/mainSee also:
ExaBGP 4.x does NOT send acknowledgments.
Pattern (fire-and-forget):
#!/usr/bin/env python3
import sys
import time
# Send commands (no ACK)
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
sys.stdout.flush()
# Add delay to avoid overwhelming ExaBGP
time.sleep(0.1)Issues:
- β No confirmation of success/failure
- β Hard to debug command errors
- β Can't detect ExaBGP shutdown
Upgrade to ExaBGP 5.x/main for ACK support.
Symptom: Routes not announced, no error message.
Cause: Forgot to flush STDOUT.
Fix:
# β WRONG
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
# Buffer not flushed!
# β
CORRECT
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
sys.stdout.flush() # Always flush!Symptom (ExaBGP 5.x): error response.
Cause: Invalid command syntax.
Examples:
# β Missing next-hop
announce route 100.10.0.100/32
# β
Correct
announce route 100.10.0.100/32 next-hop self
# β Invalid FlowSpec syntax
announce flow route { match { source 10.0.0.0/8 } } # Missing 'then'
# β
Correct
announce flow route { match { source 10.0.0.0/8; } then { discard; } }Fix: Check command syntax against this reference.
Symptom: Route not withdrawn.
Cause: Withdrawal doesn't match announcement exactly.
Example:
# Announce with community
announce route 100.10.0.100/32 next-hop self community [65001:100]
# β Withdraw without community (doesn't match)
withdraw route 100.10.0.100/32 next-hop self
# β
Withdraw with same attributes
withdraw route 100.10.0.100/32 next-hop self community [65001:100]Fix: Withdrawal must match all attributes from announcement.
Symptom (ExaBGP 5.x): Process blocks after sending command.
Cause: Not reading ACK response from STDIN.
Fix:
# β WRONG (blocks forever)
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
sys.stdout.flush()
# ExaBGP waiting to send 'done', but we're not reading!
# β
CORRECT
sys.stdout.write("announce route 100.10.0.100/32 next-hop self\n")
sys.stdout.flush()
# Read ACK
response = sys.stdin.readline().strip() # or use select()Symptom: Routes not announced, ExaBGP unresponsive.
Cause: Overwhelming ExaBGP with rapid commands.
Fix:
# β WRONG (too fast)
for prefix in range(1000):
sys.stdout.write(f"announce route 10.0.{prefix}.0/24 next-hop self\n")
sys.stdout.flush()
# β
CORRECT (batched)
for prefix in range(1000):
sys.stdout.write(f"announce route 10.0.{prefix}.0/24 next-hop self\n")
if prefix % 100 == 0:
sys.stdout.flush()
time.sleep(0.1) # Give ExaBGP time to process
sys.stdout.flush()Or use flush command:
for prefix in range(1000):
sys.stdout.write(f"announce route 10.0.{prefix}.0/24 next-hop self\n")
sys.stdout.write("flush\n")
sys.stdout.flush()- Text API Reference - Detailed examples for all address families
- JSON API Reference - Receiving BGP messages from ExaBGP
- API Overview - API architecture and patterns
- Configuration Syntax - Process configuration
- Quick Start - First API script
- FlowSpec Overview - FlowSpec examples
- Production Best Practices - Error handling, logging, monitoring
- Health Checks Guide - Health check patterns
Need help? Join the ExaBGP Slack or check GitHub Discussions β
π» 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)