Skip to content

From 3.4 to 4.x

Thomas Mangin edited this page Nov 15, 2025 · 6 revisions

Migration from ExaBGP 3.x to 4.x

Complete guide for upgrading from ExaBGP 3.x to 4.x

⚠️ CRITICAL: You MUST Upgrade from 3.x

ExaBGP 3.x uses Python 2, which is deprecated and no longer supported. Python 2 reached end-of-life on January 1, 2020 and receives no security updates.

All users must upgrade to ExaBGP 4.x or 5.0.0 for security and compatibility.

⚠️ Breaking Changes: ExaBGP 3.x β†’ 4.x includes breaking changes requiring configuration and code updates.

ℹ️ About ExaBGP 5.0.0: If you're considering upgrading beyond 4.x, note that ExaBGP 5.0.0 introduces additional breaking changes from 4.x (Python 3.8+, JSON API changes). See 4.x β†’ 5.0.0 Migration Guide for details. Most users should upgrade to 4.x first, then decide if 5.0.0 is needed.


Table of Contents


Overview

Release: ExaBGP 4.0.0 (~2017)

Severity: 🟑 MODERATE - Configuration and some API changes required

Timeline: ExaBGP 3.x is deprecated and no longer maintained. All users should upgrade to 4.x.


Should You Upgrade?

βœ… YES - You MUST Upgrade

ExaBGP 3.x is built on Python 2, which is:

  • ❌ End-of-life since January 1, 2020
  • ❌ No security patches or updates
  • ❌ Removed from most modern Linux distributions
  • ❌ Incompatible with modern Python packages

All ExaBGP 3.x users must upgrade immediately for:

  • βœ… Security updates and patches
  • βœ… Python 3 support (Python 2 is dead)
  • βœ… New features (FlowSpec improvements, EVPN, BGP-LS, etc.)
  • βœ… Better performance and stability
  • βœ… Modern BGP features (ADD-PATH, extended next-hop, etc.)
  • βœ… Continued maintenance and support

Plan Your Migration:

⚠️ Configuration files need manual updates ⚠️ JSON output format changed (if using JSON parser) ⚠️ Some command-line arguments changed ⚠️ Test thoroughly before production deployment


What Changed

Breaking Changes

Area Change Impact
Configuration Syntax changes πŸ”΄ HIGH - Manual updates required
JSON Format Output structure changed 🟑 MEDIUM - Parser updates needed
CLI Arguments Some flags changed 🟑 MEDIUM - Script updates needed
API Commands Minor syntax changes 🟒 LOW - Most commands compatible

New Features in 4.x

  • βœ… Full FlowSpec support (RFC 5575)
  • βœ… EVPN support (RFC 7432)
  • βœ… BGP-LS support (RFC 7752)
  • βœ… ADD-PATH support (RFC 7911)
  • βœ… Extended next-hop (RFC 5549)
  • βœ… Python 3 support
  • βœ… Better error messages
  • βœ… Improved performance

Configuration Syntax Changes

Major Configuration Changes

The configuration file syntax changed significantly between 3.x and 4.x.

Example: Basic Neighbor Configuration

ExaBGP 3.x:

neighbor 192.168.1.1 {
    router-id 192.168.1.2;
    local-address 192.168.1.2;
    local-as 65001;
    peer-as 65000;

    # 3.x syntax
    capability {
        route-refresh;
        graceful-restart 120;
    }
}

ExaBGP 4.x:

neighbor 192.168.1.1 {
    router-id 192.168.1.2;
    local-address 192.168.1.2;
    local-as 65001;
    peer-as 65000;

    # 4.x syntax - similar but some keywords changed
    capability {
        route-refresh enable;
        graceful-restart 120;
    }
}

Process Configuration Changes

ExaBGP 3.x:

process announce {
    run /usr/local/bin/announce.py;
}

neighbor 192.168.1.1 {
    # ... neighbor config ...
    process announce;
}

ExaBGP 4.x:

process announce {
    run /usr/local/bin/announce.py;
    encoder text;  # New: explicit encoder
}

neighbor 192.168.1.1 {
    # ... neighbor config ...

    api {
        processes [ announce ];  # New: api block
    }
}

Family Configuration Changes

ExaBGP 3.x:

neighbor 192.168.1.1 {
    # ... neighbor config ...

    family {
        ipv4 unicast;
        ipv4 flow;
    }
}

ExaBGP 4.x:

neighbor 192.168.1.1 {
    # ... neighbor config ...

    family {
        ipv4 unicast;
        ipv4 flow;
    }
}

Note: Family syntax is similar, but some address family names changed.


JSON Format Changes

JSON Output Structure Changed

If you use encoder json to receive BGP updates, the JSON format changed significantly.

Example: Route Announcement

ExaBGP 3.x JSON:

{
  "type": "update",
  "neighbor": "192.168.1.1",
  "announce": {
    "ipv4 unicast": {
      "100.10.0.0/24": {
        "next-hop": "192.168.1.2"
      }
    }
  }
}

ExaBGP 4.x JSON:

{
  "exabgp": "4.2.25",
  "time": 1699564800.0,
  "type": "update",
  "neighbor": {
    "address": {
      "local": "192.168.1.2",
      "peer": "192.168.1.1"
    },
    "asn": {
      "local": 65001,
      "peer": 65000
    },
    "message": {
      "update": {
        "announce": {
          "ipv4 unicast": {
            "100.10.0.0/24": [
              {
                "next-hop": "192.168.1.2"
              }
            ]
          }
        }
      }
    }
  }
}

Changes:

  • More structured (nested neighbor object)
  • Added metadata (exabgp, time, asn)
  • Route attributes now in arrays
  • More detailed peer information

Impact: Programs parsing JSON output need updates.


Command-Line Changes

CLI Argument Changes

Some command-line arguments changed between 3.x and 4.x.

ExaBGP 3.x:

# 3.x command line
exabgp --debug /etc/exabgp/exabgp.conf
exabgp --help

ExaBGP 4.x:

# 4.x command line (mostly compatible)
exabgp /etc/exabgp/exabgp.conf
exabgp --help
exabgp --version

Environment Variables (mostly compatible):

# Both 3.x and 4.x
export exabgp.daemon.user=exabgp
export exabgp.log.level=INFO
export exabgp.log.destination=stdout

# 4.x added
export exabgp.api.ack=true

API Changes

API Command Compatibility

Most API commands are compatible between 3.x and 4.x.

Commands That Work in Both Versions

# These work identically in 3.x and 4.x
announce route 100.10.0.0/24 next-hop self
withdraw route 100.10.0.0/24
announce flow route { match { destination 100.10.0.0/24; } then { discard; } }

New Commands in 4.x

# New in 4.x
announce attributes next-hop self nlri 100.10.0.0/24 100.20.0.0/24  # Bulk announcements
clear adj-rib out
flush adj-rib out

ACK Feature (4.x Only)

ExaBGP 3.x:

  • No ACK responses
  • Fire-and-forget commands
  • No way to know if command succeeded

ExaBGP 4.x:

  • ACK enabled by default
  • Sends done, error, shutdown responses
  • Programs can verify command success

Migration Note: If your 3.x programs don't read STDIN, they will hang in 4.x unless you:

  • Option 1: Update programs to read ACK responses (recommended)
  • Option 2: Disable ACK (choose based on ExaBGP version):
    • Environment variable: export exabgp.api.ack=false (4.x and 5.x)
    • Runtime command: Send disable-ack or silence-ack (5.x/main only)

See ACK Feature Documentation for details.


Migration Steps

Step 1: Backup Everything

# Backup configuration
cp /etc/exabgp/exabgp.conf /etc/exabgp/exabgp.conf.3x.backup

# Backup API programs
tar czf /tmp/exabgp-api-programs-backup.tar.gz /usr/local/bin/exabgp-*

# Document current version
exabgp --version > /tmp/exabgp-version-3x.txt

Step 2: Install ExaBGP 4.x (Test Environment)

Option A: Using pip (recommended):

# Install ExaBGP 4.x
pip3 install exabgp

# Verify version
exabgp --version
# Should show: ExaBGP 4.2.x

Option B: From source:

git clone https://github.com/Exa-Networks/exabgp.git
cd exabgp
git checkout 4.2  # Use latest 4.2.x tag
pip3 install .

Step 3: Update Configuration File

Automated conversion (if available):

# No official converter exists - manual updates required

Manual updates:

  1. Read through your 3.x configuration
  2. Check configuration syntax in Configuration Syntax Guide
  3. Update process blocks to use api { } structure
  4. Add encoder directive to process blocks
  5. Verify family statements

Example conversion:

Before (3.x):

process announce {
    run /usr/local/bin/announce.py;
}

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 unicast;
    }

    process announce;
}

After (4.x):

process announce {
    run /usr/local/bin/announce.py;
    encoder text;  # Added
}

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 unicast;
    }

    api {  # Changed
        processes [ announce ];
    }
}

Step 4: Test Configuration Syntax

# Test configuration parsing
exabgp --test /etc/exabgp/exabgp.conf

# If errors occur, check:
# - Process block syntax (api { } structure)
# - encoder directives
# - Family statements

Step 5: Update API Programs (If Using JSON)

If you use encoder json and parse JSON output:

Update JSON parser:

# 3.x parser
def parse_3x(line):
    msg = json.loads(line)
    if msg['type'] == 'update':
        routes = msg['announce']['ipv4 unicast']
        # ...

# 4.x parser
def parse_4x(line):
    msg = json.loads(line)
    if msg['type'] == 'update':
        routes = msg['neighbor']['message']['update']['announce']['ipv4 unicast']
        # ...

Step 6: Handle ACK Feature

If your programs don't read STDIN:

Option 1 - Disable ACK (simpler, but no error feedback):

# Environment variable (works on 4.x and 5.x)
export exabgp.api.ack=false
exabgp /etc/exabgp/exabgp.conf

# OR runtime command (5.x/main only)
# Send: disable-ack or silence-ack

Option 2 - Update programs to read ACK (recommended):

#!/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 (new in 4.x).
    ExaBGP may not respond immediately, so we poll with sleep.
    Handles both text and JSON encoder formats.
    """
    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

# Send command
sys.stdout.write("announce route 100.10.0.0/24 next-hop self\n")
sys.stdout.flush()

# Read ACK (new in 4.x, with robust polling)
if not wait_for_ack():
    sys.exit(1)  # Command failed

Step 7: Test in Non-Production

# Start ExaBGP 4.x
exabgp /etc/exabgp/exabgp.conf

# Verify:
# 1. Configuration loads without errors
# 2. BGP session establishes
# 3. API programs run without hanging
# 4. Routes are announced correctly
# 5. Updates are received correctly (if using JSON)

Check logs:

tail -f /var/log/exabgp.log

Step 8: Deploy to Production

Deployment strategy:

  1. Rolling upgrade (if possible):

    • Upgrade one ExaBGP instance at a time
    • Verify BGP sessions and routes
    • Move to next instance
  2. Blue/Green deployment:

    • Run 4.x alongside 3.x
    • Gradually shift traffic to 4.x
    • Retire 3.x when stable
  3. Maintenance window:

    • Schedule downtime
    • Upgrade all instances
    • Verify before restoring service

Testing Your Migration

Checklist

Configuration:

  • Configuration file loads without errors
  • All neighbors defined correctly
  • Process blocks use correct syntax
  • Families match your requirements

BGP Sessions:

  • Sessions establish successfully
  • Routes are exchanged
  • Attributes are correct (next-hop, AS-PATH, etc.)
  • FlowSpec rules work (if using)

API Programs:

  • Programs start without errors
  • Commands are accepted
  • Programs don't hang
  • ACK responses handled (if enabled)
  • JSON parsing works (if using)

Monitoring:

  • Logs show no errors
  • Route counts match expectations
  • No unexpected BGP session resets
  • API programs remain running

Rollback Plan

If Migration Fails

Quick rollback:

# Stop ExaBGP 4.x
systemctl stop exabgp

# Reinstall 3.x
pip uninstall exabgp
pip install exabgp==3.4.30  # Last 3.x version

# Restore configuration
cp /etc/exabgp/exabgp.conf.3x.backup /etc/exabgp/exabgp.conf

# Restart
systemctl start exabgp

Verify rollback:

exabgp --version
# Should show: ExaBGP 3.4.x

# Check BGP sessions
exabgpcli show neighbor summary

Common Issues

Issue #1: Configuration Parse Errors

Symptom:

ERROR: Could not parse configuration
ERROR: Syntax error at line X

Solution:

  • Check process block uses api { processes [ ... ]; } syntax
  • Ensure encoder directive present in process blocks
  • Verify neighbor blocks use correct keywords

Issue #2: API Programs Hang

Symptom:

  • API program starts but becomes unresponsive
  • ExaBGP stops processing commands

Cause: ACK feature enabled (default in 4.x), but program doesn't read responses

Solution:

Option 1 - Disable ACK:

# Environment variable (works on 4.x and 5.x)
export exabgp.api.ack=false
exabgp /etc/exabgp/exabgp.conf

# OR runtime command (5.x/main only)
# Send: disable-ack or silence-ack

Option 2 - Read ACK responses:

# Add ACK handling to your program
import select
ready, _, _ = select.select([sys.stdin], [], [], 5.0)
if ready:
    response = sys.stdin.readline().strip()

Issue #3: JSON Parsing Fails

Symptom:

KeyError: 'announce'
KeyError: 'neighbor'

Cause: JSON structure changed in 4.x

Solution: Update JSON parser to use new structure:

# 3.x path
msg['announce']['ipv4 unicast']

# 4.x path
msg['neighbor']['message']['update']['announce']['ipv4 unicast']

Issue #4: Routes Not Announced

Symptom:

  • API program runs
  • No errors in logs
  • Routes not appearing on router

Possible causes:

  1. ACK responses not read - Program hangs, commands not processed
  2. Family mismatch - Neighbor not configured for correct address family
  3. Next-hop unreachable - Router can't reach next-hop IP
  4. BGP session not established - Check session state

Debug:

# Check ExaBGP logs
tail -f /var/log/exabgp.log

# Check BGP session
exabgpcli show neighbor 192.168.1.1

# Check process is running
ps aux | grep announce.py

Version Comparison Table

Feature 3.x 4.x
Configuration Syntax Old format New format (breaking)
JSON Output Simple structure Detailed structure (breaking)
ACK Responses ❌ No βœ… Yes (default)
Python 2 βœ… Supported ⚠️ Deprecated
Python 3 ⚠️ Limited βœ… Fully supported
FlowSpec Basic Full RFC 5575
EVPN ❌ No βœ… Yes (RFC 7432)
BGP-LS ❌ No βœ… Yes (RFC 7752)
ADD-PATH ❌ No βœ… Yes (RFC 7911)
Extended Next-Hop ❌ No βœ… Yes (RFC 5549)
Performance Good Better
Maintenance ❌ Deprecated βœ… Active

After Migration

Verify Everything Works

Monitor for 24-48 hours:

  • BGP sessions remain stable
  • Routes are correct
  • No unexpected session resets
  • API programs remain running
  • No memory leaks
  • Logs show no errors

Update Documentation

  • Document your 4.x configuration
  • Update runbooks with 4.x commands
  • Train team on 4.x differences
  • Update monitoring/alerting for 4.x

Next Steps

Once stable on 4.x:

  • Stay on 4.x for production (recommended)
  • Consider 5.x/main only if you need bleeding-edge features
  • 4.x and 5.x are fully compatible (no breaking changes)

Getting Help

Resources

Community Support


See Also


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

Clone this wiki locally