-
Notifications
You must be signed in to change notification settings - Fork 461
Text API Reference
Complete reference for ExaBGP's text-based API commands
- Overview
- Command Syntax
- IPv4/IPv6 Unicast
- Route Attributes
- FlowSpec
- L3VPN
- EVPN
- BGP-LS
- VPLS
- Operational Commands
- Examples by Use Case
- Common Errors
The text encoder uses human-readable commands for announcing and withdrawing routes.
Configuration:
process my-program {
run /etc/exabgp/api/announce.py;
encoder text;
}Usage in your program:
import sys
# Announce a route
sys.stdout.write("announce route 100.10.0.0/24 next-hop self\n")
sys.stdout.flush() # CRITICAL - always flush!
# Withdraw a route
sys.stdout.write("withdraw route 100.10.0.0/24\n")
sys.stdout.flush()<action> <family> <prefix> [attributes]
Actions:
-
announce- Add/update a route -
withdraw- Remove a route
Families:
-
route- IPv4/IPv6 unicast -
flow- FlowSpec -
vpn- L3VPN -
evpn- EVPN
-
Always end with newline (
\n) -
Always flush after write (
sys.stdout.flush()) - One command per line
-
Case-sensitive (
announcenotANNOUNCE)
IPv4:
# Using 'self' (recommended)
print("announce route 100.10.0.0/24 next-hop self")
# Explicit next-hop
print("announce route 100.10.0.0/24 next-hop 192.168.1.2")
# /32 host route
print("announce route 100.10.0.100/32 next-hop self")IPv6:
# IPv6 prefix
print("announce route 2001:db8::/32 next-hop self")
# IPv6 /128 host route
print("announce route 2001:db8::100/128 next-hop self")# IPv4
print("withdraw route 100.10.0.0/24")
# IPv6
print("withdraw route 2001:db8::/32")
# Note: No need to specify next-hop or attributes when withdrawingUsing 'self' (recommended):
print("announce route 100.10.0.0/24 next-hop self")
# ExaBGP auto-fills with local-addressExplicit next-hop:
print("announce route 100.10.0.0/24 next-hop 192.168.1.2")
print("announce route 2001:db8::/32 next-hop 2001:db8::1")Third-party next-hop:
# Tell peer to use different next-hop
print("announce route 100.10.0.0/24 next-hop 10.0.0.1")Lower MED is preferred. Use for traffic engineering.
# Preferred path (lower MED)
print("announce route 100.10.0.0/24 next-hop self med 50")
# Backup path (higher MED)
print("announce route 100.10.0.0/24 next-hop self med 100")Higher local-preference is preferred. iBGP only.
# Preferred path (higher local-pref)
print("announce route 100.10.0.0/24 next-hop self local-preference 200")
# Less preferred
print("announce route 100.10.0.0/24 next-hop self local-preference 100")Normal announcement:
print("announce route 100.10.0.0/24 next-hop self")
# AS path: [ 65001 ] (your local-as)AS path prepending:
# Prepend your AS twice
print("announce route 100.10.0.0/24 next-hop self as-path [ 65001 65001 65001 ]")
# AS path becomes: 65001 65001 65001 (looks like longer path)Custom AS path:
# Announce as if from different AS
print("announce route 100.10.0.0/24 next-hop self as-path [ 65002 65003 ]")Standard communities (RFC 1997):
# Single community
print("announce route 100.10.0.0/24 next-hop self community [ 65001:100 ]")
# Multiple communities
print("announce route 100.10.0.0/24 next-hop self community [ 65001:100 65001:200 ]")
# Well-known communities
print("announce route 100.10.0.0/24 next-hop self community [ no-export ]")
print("announce route 100.10.0.0/24 next-hop self community [ no-advertise ]")Well-known communities:
-
no-export(0xFFFFFF01) - Don't advertise to eBGP peers -
no-advertise(0xFFFFFF02) - Don't advertise to any peer -
no-export-subconfed(0xFFFFFF03) - Don't export outside confederation
Extended communities (RFC 4360):
# Route target
print("announce route 100.10.0.0/24 next-hop self extended-community [ target:65001:100 ]")
# Route origin
print("announce route 100.10.0.0/24 next-hop self extended-community [ origin:65001:100 ]")
# Multiple
print("announce route 100.10.0.0/24 next-hop self extended-community [ target:65001:100 target:65001:200 ]")Large communities (RFC 8092):
# Format: global:local1:local2
print("announce route 100.10.0.0/24 next-hop self large-community [ 65001:100:200 ]")# IGP origin (default)
print("announce route 100.10.0.0/24 next-hop self origin igp")
# EGP origin
print("announce route 100.10.0.0/24 next-hop self origin egp")
# Incomplete origin
print("announce route 100.10.0.0/24 next-hop self origin incomplete")# Complex announcement with multiple attributes
print("announce route 100.10.0.0/24 next-hop self "
"med 100 "
"local-preference 200 "
"community [ 65001:100 65001:200 ] "
"as-path [ 65001 ]")FlowSpec allows BGP-based traffic filtering. ExaBGP pioneered open-source FlowSpec support (now also in GoBGP, FRRouting, BIRD).
announce flow route {
match {
<match-conditions>
}
then {
<actions>
}
}Destination prefix:
print("announce flow route { "
"match { destination 100.10.0.0/24; } "
"then { discard; } "
"}")Source prefix:
print("announce flow route { "
"match { source 10.0.0.0/8; } "
"then { discard; } "
"}")Ports:
# Destination port
print("announce flow route { "
"match { destination-port =80; } "
"then { discard; } "
"}")
# Source port
print("announce flow route { "
"match { source-port =1234; } "
"then { discard; } "
"}")
# Port range
print("announce flow route { "
"match { destination-port >=1024&<=65535; } "
"then { discard; } "
"}")Port operators:
-
=80- Equals 80 -
>1023- Greater than 1023 -
<1024- Less than 1024 -
>=1024- Greater than or equal -
<=65535- Less than or equal -
>=1024&<=65535- Range (AND)
Protocol:
# TCP (6)
print("announce flow route { "
"match { protocol =tcp; } "
"then { discard; } "
"}")
# UDP (17)
print("announce flow route { "
"match { protocol =udp; } "
"then { discard; } "
"}")
# ICMP (1)
print("announce flow route { "
"match { protocol =icmp; } "
"then { discard; } "
"}")
# Numeric
print("announce flow route { "
"match { protocol =6; } "
"then { discard; } "
"}")TCP flags:
# SYN flag set
print("announce flow route { "
"match { tcp-flags [ syn ]; } "
"then { discard; } "
"}")
# SYN+ACK
print("announce flow route { "
"match { tcp-flags [ syn ack ]; } "
"then { discard; } "
"}")
# All flags
print("announce flow route { "
"match { tcp-flags [ fin syn rst psh ack urg ]; } "
"then { discard; } "
"}")Packet length:
print("announce flow route { "
"match { packet-length >=1000; } "
"then { discard; } "
"}")ICMP type/code:
# ICMP echo request (type 8)
print("announce flow route { "
"match { icmp-type =8; } "
"then { discard; } "
"}")
# ICMP echo reply (type 0)
print("announce flow route { "
"match { icmp-type =0; icmp-code =0; } "
"then { discard; } "
"}")DSCP (Differentiated Services Code Point):
print("announce flow route { "
"match { dscp =46; } "
"then { discard; } "
"}")Fragment:
# Fragmented packets
print("announce flow route { "
"match { fragment [ is-fragment ]; } "
"then { discard; } "
"}")
# First fragment
print("announce flow route { "
"match { fragment [ first-fragment ]; } "
"then { discard; } "
"}")
# Not a fragment
print("announce flow route { "
"match { fragment [ not-a-fragment ]; } "
"then { discard; } "
"}")# Block SYN floods to port 80 from 10.0.0.0/8
print("announce flow route { "
"match { "
"source 10.0.0.0/8; "
"destination-port =80; "
"protocol =tcp; "
"tcp-flags [ syn ]; "
"} "
"then { discard; } "
"}")Discard (drop):
print("announce flow route { "
"match { destination 100.10.0.0/24; } "
"then { discard; } "
"}")Rate-limit:
# Limit to 1 Mbps (1000000 bytes/sec)
print("announce flow route { "
"match { destination 100.10.0.0/24; } "
"then { rate-limit 1000000; } "
"}")
# Limit to 10 Mbps
print("announce flow route { "
"match { source 10.0.0.0/8; } "
"then { rate-limit 10000000; } "
"}")Redirect to VRF:
print("announce flow route { "
"match { destination 100.10.0.0/24; } "
"then { redirect 65001:100; } "
"}")Mark (DSCP remarking):
print("announce flow route { "
"match { destination 100.10.0.0/24; } "
"then { mark 46; } "
"}")Community (tagging):
print("announce flow route { "
"match { destination 100.10.0.0/24; } "
"then { community [ 65001:666 ]; } "
"}")# Withdraw by match conditions
print("withdraw flow route { "
"match { destination 100.10.0.0/24; } "
"}")Block DDoS attack:
# Block UDP flood from 10.0.0.0/8 to DNS port
print("announce flow route { "
"match { "
"source 10.0.0.0/8; "
"destination-port =53; "
"protocol =udp; "
"} "
"then { discard; } "
"}")Rate-limit HTTP traffic:
# Limit HTTP to 100 Mbps per source
print("announce flow route { "
"match { "
"destination-port =80; "
"protocol =tcp; "
"} "
"then { rate-limit 100000000; } "
"}")Block large packets (possible attack):
# Drop packets > 1500 bytes
print("announce flow route { "
"match { packet-length >1500; } "
"then { discard; } "
"}")Layer 3 VPN (RFC 4364) for MPLS VPNs.
# Basic L3VPN route
print("announce vpn 100.10.0.0/24 "
"next-hop self "
"route-distinguisher 65001:100 "
"label 10000")
# With route target
print("announce vpn 100.10.0.0/24 "
"next-hop self "
"route-distinguisher 65001:100 "
"extended-community [ target:65001:100 ] "
"label 10000")
# Multiple route targets (export to multiple VRFs)
print("announce vpn 100.10.0.0/24 "
"next-hop self "
"route-distinguisher 65001:100 "
"extended-community [ target:65001:100 target:65001:200 ] "
"label 10000")print("withdraw vpn 100.10.0.0/24 route-distinguisher 65001:100")Ethernet VPN (RFC 7432) for data center fabrics.
MAC only:
print("announce evpn mac-ip "
"aa:bb:cc:dd:ee:ff "
"route-distinguisher 65001:100 "
"next-hop self "
"label [ 10000 ] "
"extended-community [ target:65001:100 ]")MAC + IP:
print("announce evpn mac-ip "
"aa:bb:cc:dd:ee:ff 100.10.0.100 "
"route-distinguisher 65001:100 "
"next-hop self "
"label [ 10000 ] "
"extended-community [ target:65001:100 ]")With VNI (VXLAN):
print("announce evpn mac-ip "
"aa:bb:cc:dd:ee:ff 100.10.0.100 "
"route-distinguisher 65001:100 "
"next-hop self "
"label [ 5000 ] "
"extended-community [ target:65001:100 encapsulation:vxlan ]")print("announce evpn multicast "
"100.10.0.1 "
"route-distinguisher 65001:100 "
"next-hop self "
"extended-community [ target:65001:100 ]")print("withdraw evpn mac-ip aa:bb:cc:dd:ee:ff route-distinguisher 65001:100")BGP Link-State (RFC 7752) for topology collection.
Note: BGP-LS is typically receive-only in ExaBGP. Used for collecting topology information from IGP.
Configuration to receive BGP-LS:
neighbor 192.168.1.1 {
router-id 192.168.1.2;
local-address 192.168.1.2;
local-as 65001;
peer-as 65000;
family {
ipv4 link-state;
ipv6 link-state;
}
api {
processes [ receive-topology ];
}
}No text API for announcing BGP-LS - it's receive-only.
Virtual Private LAN Service (L2VPN).
# VPLS route
print("announce vpls "
"route-distinguisher 65001:100 "
"endpoint 192.168.1.2 "
"offset 10 "
"size 8 "
"base 10000 "
"extended-community [ target:65001:100 ]")print("withdraw vpls route-distinguisher 65001:100")Force route refresh (send all routes again):
print("announce route-refresh ipv4 unicast")
print("announce route-refresh ipv6 unicast")Send operational messages:
# Query operational state
print("operational afi ipv4 safi unicast advisory rib in")Announce service IP when healthy:
import sys
import time
import socket
SERVICE_IP = "100.10.0.100"
SERVICE_PORT = 80
def is_healthy():
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((SERVICE_IP, SERVICE_PORT))
sock.close()
return result == 0
except:
return False
time.sleep(2)
announced = False
while True:
if is_healthy():
if not announced:
sys.stdout.write(f"announce route {SERVICE_IP}/32 next-hop self\n")
sys.stdout.flush()
announced = True
else:
if announced:
sys.stdout.write(f"withdraw route {SERVICE_IP}/32\n")
sys.stdout.flush()
announced = False
time.sleep(5)Auto-block detected attacks:
import sys
import time
def detect_attack():
# Your DDoS detection logic
# Returns (source_ip, dest_port, protocol) if attack detected
return ("10.0.0.0/8", 80, "tcp")
time.sleep(2)
while True:
attack = detect_attack()
if attack:
source, port, proto = attack
# Block the attack
sys.stdout.write(
f"announce flow route {{ "
f"match {{ source {source}; destination-port ={port}; protocol ={proto}; }} "
f"then {{ discard; }} "
f"}}\n"
)
sys.stdout.flush()
sys.stderr.write(f"[BLOCKED] Attack from {source} to port {port}\n")
time.sleep(1)Announce with different metrics for load distribution:
import sys
import time
time.sleep(2)
# This server gets most traffic (lower MED)
sys.stdout.write("announce route 100.10.0.100/32 next-hop self med 100\n")
sys.stdout.flush()
# Another server as backup (higher MED)
# On the other server, announce with med 200Prefer specific path with communities:
import sys
import time
time.sleep(2)
# Mark route with community for policy
sys.stdout.write(
"announce route 100.10.0.0/24 next-hop self "
"community [ 65001:100 ] "
"local-preference 200\n"
)
sys.stdout.flush()Wrong:
print("announce route 100.10.0.0/24 next-hop self")
# Nothing happens - stuck in bufferCorrect:
print("announce route 100.10.0.0/24 next-hop self")
sys.stdout.flush() # Now it worksWrong:
print("announce route 100.10.0.0/24")
# Error: next-hop requiredCorrect:
print("announce route 100.10.0.0/24 next-hop self")Wrong:
print("announce 100.10.0.0/24 next-hop self")
# Missing 'route' keywordCorrect:
print("announce route 100.10.0.0/24 next-hop self")Wrong:
print("announce flow route match destination 100.10.0.0/24 then discard")
# Missing { } bracesCorrect:
print("announce flow route { match { destination 100.10.0.0/24; } then { discard; } }")Wrong:
print("withdraw route 100.10.0.0/24 next-hop self")
# Withdraw doesn't need attributesCorrect:
print("withdraw route 100.10.0.0/24")announce route <prefix> next-hop self [attributes]
withdraw route <prefix>announce flow route { match { <conditions>; } then { <action>; } }
withdraw flow route { match { <conditions>; } }announce vpn <prefix> next-hop self route-distinguisher <rd> label <label> [extended-community [...]]
withdraw vpn <prefix> route-distinguisher <rd>announce evpn mac-ip <mac> [<ip>] route-distinguisher <rd> next-hop self label [<label>] extended-community [...]
withdraw evpn mac-ip <mac> route-distinguisher <rd>- API Overview - API architecture and concepts
- JSON API Reference - JSON message format
- API Commands - Complete command reference
- FlowSpec Overview - FlowSpec detailed guide
- Configuration Syntax - Process configuration
Need JSON format? See JSON API Reference →
👻 Ghost written by Claude (Anthropic AI)
Getting Started
Configuration
- Configuration Syntax
- Neighbor Configuration
- Directives A-Z
- Templates
- Environment Variables
- Process Configuration
API
- API Overview
- Text API Reference
- JSON API Reference
- API Commands
- Writing API Programs
- Error Handling
- Production Best Practices
Address Families
- Overview
- IPv4 Unicast
- IPv6 Unicast
- FlowSpec
- EVPN
- L3VPN
- BGP-LS
- VPLS
- SRv6 / MUP
- Multicast
- RT Constraint
Features
Use Cases
Tools
Operations
Reference
- Architecture
- Design
- Attribute Reference
- Command Reference
- BGP State Machine
- Capabilities
- Communities
- Examples Index
- Glossary
- RFC Support
Integration
Migration
Community
External