-
Notifications
You must be signed in to change notification settings - Fork 458
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
- 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.x send ACK responses by default (
done/error/shutdown) - βΉοΈ ACK can be disabled with
exabgp.api.ack=falsefor simpler programs
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.x/main, safe on 4.x)
enable-ackBehavior:
- β ExaBGP 5.x/main: 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.x/main, safe on 4.x)
disable-ackBehavior:
- β ExaBGP 5.x/main: 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.x/main
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.x/main, safe on 4.x)
silence-ackBehavior:
- β ExaBGP 5.x/main: 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)