Skip to content

API Commands

Thomas Mangin edited this page Nov 10, 2025 · 3 revisions

API Commands Reference

A-Z alphabetical reference for all ExaBGP API commands

πŸ“š For detailed examples and patterns, see Text API Reference and JSON API Reference


Table of Contents


Command Format

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 does NOT send ACK (silent)
  • βœ… ExaBGP 5.x/main sends ACK (done/error/shutdown)

Announce Commands

Commands to advertise BGP routes.

announce route

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 50

Attributes:

  • 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 flow

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 vpnv4

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 vpnv6

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 16

See also:


announce evpn

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

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:


announce refresh

Request route refresh from peer

announce refresh <afi> <safi>

Examples:

# Request IPv4 unicast refresh
announce refresh ipv4 unicast

# Request FlowSpec refresh
announce refresh ipv4 flowspec

See also:


Withdraw Commands

Commands to remove previously announced routes.

withdraw route

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/32

Important: Withdrawal must match announcement (prefix + next-hop + attributes).

See also:


withdraw flow

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 vpnv4

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:100

withdraw vpnv6

Withdraw 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:100

withdraw evpn

Withdraw EVPN route

withdraw evpn macadvertisement aa:bb:cc:dd:ee:ff 100.10.0.1 1000 rd 65001:100

withdraw vpls

Withdraw VPLS route

withdraw vpls 192.168.1.1 10 8 rd 65001:100

Operational Commands

Commands for BGP session control and monitoring.

shutdown

Gracefully shutdown ExaBGP

shutdown

Example:

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

Restart BGP connection to peer

restart

Example:

# Restart after configuration change
sys.stdout.write("restart\n")
sys.stdout.flush()

Effect:

  • Closes existing connections
  • Re-reads configuration
  • Establishes new connections

reload

Reload configuration without restarting

reload

Effect:

  • Re-reads configuration file
  • Applies changes without dropping sessions (if possible)

version

Query ExaBGP version

version

Response (on STDIN):

exabgp 4.2.25

Control Commands

Commands for flow control and debugging.

flush

Flush pending route updates

flush

Use 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.


Quick Reference Table

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

Command Acknowledgment (ACK)

ExaBGP 5.x/main (ACK Enabled)

ExaBGP 5.x and main branch send command acknowledgments via STDIN.

Response types:

done       # Command succeeded
error      # Command failed
shutdown   # ExaBGP is shutting down

Pattern with select():

#!/usr/bin/env python3
import sys
import select

def send_command(command):
    """Send command and wait for ACK"""
    # Send command
    sys.stdout.write(command + "\n")
    sys.stdout.flush()

    # Wait for response (5 second timeout)
    ready, _, _ = select.select([sys.stdin], [], [], 5.0)

    if ready:
        response = sys.stdin.readline().strip()
        if response == "done":
            sys.stderr.write(f"[SUCCESS] {command}\n")
            return True
        elif response == "error":
            sys.stderr.write(f"[ERROR] Command failed: {command}\n")
            return False
        elif response == "shutdown":
            sys.stderr.write(f"[SHUTDOWN] ExaBGP is shutting down\n")
            sys.exit(0)
    else:
        sys.stderr.write(f"[TIMEOUT] No response for: {command}\n")
        return False

# Use it
send_command("announce route 100.10.0.100/32 next-hop self")

Configuration:

[exabgp.api]
ack = true  # Default in 5.x/main

See also:


ExaBGP 4.x (No ACK)

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.


Common Errors

Error: Command not sent

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!

Error: Syntax error in command

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.


Error: Withdrawal doesn't match

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.


Error: Process hangs waiting for input

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()

Error: Too many commands too fast

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()

Next Steps

Learn More

Examples

Production


Need help? Join the ExaBGP Slack or check GitHub Discussions β†’


πŸ‘» Ghost written by Claude (Anthropic AI)

Clone this wiki locally