Skip to content

Communities

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

BGP Communities

BGP Communities are optional transitive attributes used to tag BGP routes for policy-based routing, traffic engineering, and route filtering. ExaBGP provides comprehensive support for Standard Communities (RFC 1997), Extended Communities (RFC 4360), and Large Communities (RFC 8092), enabling flexible route tagging and sophisticated BGP policy implementations.

Table of Contents


What are BGP Communities?

BGP Communities are tags attached to BGP routes that enable policy-based routing without relying solely on prefix or AS-path matching. Communities allow network operators to:

  • Group routes with similar characteristics
  • Apply policies based on route tags
  • Signal intent to upstream/downstream neighbors
  • Implement traffic engineering through selective route preference
  • Control route propagation across AS boundaries

Key Characteristics

  • Optional Transitive Attribute (Type Code: 8)
  • Routes can carry multiple communities
  • Preserved across AS boundaries (unless stripped)
  • No inherent meaning - semantics defined by network operators
  • Policy tool - used in route-maps, import/export filters

Community Types

ExaBGP supports three types of BGP communities:

Type RFC Size Format Use Case
Standard RFC 1997 32-bit AS:Value (16:16) General route tagging
Extended RFC 4360 64-bit Type:AS:Value VPN, Traffic Eng, QoS
Large RFC 8092 96-bit ASN:Val1:Val2 (32:32:32) Large ASN support

Compatibility:

  • βœ… Standard Communities: Universal support (all BGP implementations)
  • βœ… Extended Communities: Wide support (MPLS VPN, FlowSpec, EVPN)
  • ⚠️ Large Communities: Modern implementations only (2017+)

Standard Communities (RFC 1997)

Format

32-bit value typically represented as:

  • Decimal: AS:Value (16-bit:16-bit)
  • Hexadecimal: 0xAAAAVVVV

Example:

  • 65001:100 β†’ ASN 65001, Value 100
  • 0xFDE90064 β†’ Hexadecimal representation

Structure

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ASN (16 bits)  β”‚  Value (16 bits)β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     0-65535     β”‚     0-65535     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Example: 65001:100
         β”œβ”€β”€β”€β”€β”˜ β””β”€β”€β”˜
         AS     Value

Conventions:

  • High 16 bits: Typically AS number (administrative domain)
  • Low 16 bits: Locally significant value (policy identifier)

Well-Known Standard Communities

Community Hex Meaning Use Case
NO_EXPORT 0xFFFFFF01 Do not advertise outside confederation Local routes
NO_ADVERTISE 0xFFFFFF02 Do not advertise to any peer Blackhole local
NO_EXPORT_SUBCONFED 0xFFFFFF03 Do not advertise outside sub-confederation Confederation internal
NOPEER 0xFFFFFF04 Do not advertise to peers Upstream only
BLACKHOLE 0xFFFF029A Blackhole/discard traffic DDoS mitigation

Configuration Example

# Static route with standard communities
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;
    }

    static {
        route 10.0.0.0/8 {
            next-hop 192.168.1.2;
            community [ 65001:100 65001:200 ];  # Multiple communities
        }
    }
}

API Example (Text Format)

#!/usr/bin/env python3
import sys

# Announce route with standard communities
route = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.2 "
    "community [ 65001:100 65001:200 ]"
)

sys.stdout.write(f"{route}\n")
sys.stdout.flush()

# Well-known community: NO_EXPORT
route_no_export = (
    "announce route 172.16.0.0/12 "
    "next-hop 192.168.1.2 "
    "community [ no-export ]"  # or 65535:65281 or 0xFFFFFF01
)

sys.stdout.write(f"{route_no_export}\n")
sys.stdout.flush()

# BLACKHOLE community for DDoS mitigation
blackhole = (
    "announce route 1.2.3.4/32 "
    "next-hop 192.0.2.1 "
    "community [ blackhole ]"  # or 65535:666 or 0xFFFF029A
)

sys.stdout.write(f"{blackhole}\n")
sys.stdout.flush()

Common Standard Community Patterns

Traffic Engineering:

65001:100   # Prefer path via ISP-1
65001:200   # Prefer path via ISP-2
65001:300   # Backup path

Geographic Tagging:

65001:1000  # Routes from US-East
65001:2000  # Routes from EU-West
65001:3000  # Routes from APAC

Route Origin:

65001:10    # Customer routes
65001:20    # Peer routes
65001:30    # Upstream routes

Extended Communities (RFC 4360)

Format

64-bit value with structured format:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Type (8)   β”‚ Sub (8)    β”‚ Value (48 bits)      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0x00-0xFF  β”‚ 0x00-0xFF  β”‚ Format depends on typeβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Total: 64 bits (8 bytes)

Extended Community Types

ExaBGP supports these extended community types:

Route Target (RT)

Purpose: VPN membership (L3VPN, EVPN, L2VPN)

Formats:

# Type 0x0002: AS:Value (2-byte AS)
target:65001:100

# Type 0x0102: IP:Value
target:192.0.2.1:100

# Type 0x0202: AS:Value (4-byte AS)
target4:4200000000:100

Example:

# VPNv4 route with Route Target
route = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.2 "
    "rd 65001:1 "
    "extended-community [ target:65001:100 ]"
)

Route Origin (RO)

Purpose: Route source identification

Formats:

origin:65001:100     # 2-byte AS
origin:192.0.2.1:100 # IPv4
origin4:4200000000:100 # 4-byte AS

Traffic Engineering

Rate Limiting (FlowSpec):

# Rate limit to 1 Mbps
rate-limit:1000000

Traffic Marking:

# DSCP marking
mark:<dscp-value>

Traffic Action (FlowSpec):

# Redirect to VRF
redirect:65001:100

# Traffic rate (rate-limit in bytes/sec)
traffic-rate:0  # 0 = drop

Encapsulation

Purpose: Specify tunnel encapsulation type

Example:

encapsulation:vxlan   # VXLAN encapsulation
encapsulation:gre     # GRE encapsulation

MAC Mobility (EVPN)

Purpose: MAC address mobility in EVPN

Format:

mac-mobility:<sequence>

Configuration Example

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 vpn;  # VPNv4 uses extended communities
    }

    static {
        route 10.0.0.0/8 {
            next-hop 192.168.1.2;
            rd 65001:1;
            extended-community [ target:65001:100 origin:65001:1 ];
        }
    }
}

API Example (Extended Communities)

#!/usr/bin/env python3
import sys

# VPNv4 route with Route Target
vpn_route = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.2 "
    "rd 65001:1 "
    "label 100 "
    "extended-community [ target:65001:100 target:65001:200 ]"
)

sys.stdout.write(f"{vpn_route}\n")
sys.stdout.flush()

# FlowSpec with traffic action
flowspec = (
    "announce flow route "
    "{ match { source 1.2.3.4/32; destination-port =80; } "
    "then { rate-limit 0; } }"  # Drop traffic
)

sys.stdout.write(f"{flowspec}\n")
sys.stdout.flush()

# EVPN with MAC mobility
evpn_route = (
    "announce route-distinguisher 65001:1 "
    "ethernet-segment-identifier 00:11:22:33:44:55:66:77:88:99 "
    "extended-community [ mac-mobility:1 ]"
)

sys.stdout.write(f"{evpn_route}\n")
sys.stdout.flush()

Large Communities (RFC 8092)

Format

96-bit (12-byte) value supporting 4-byte ASNs:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ASN (32-bit) β”‚ Val1 (32-bit)β”‚ Val2 (32-bit)β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0-4294967295 β”‚ 0-4294967295 β”‚ 0-4294967295 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Example: 4200000000:100:200
         β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”˜ β””β”€β”˜
         4-byte ASN  V1  V2

Why Large Communities?

Problem with Standard Communities:

  • Limited to 16-bit AS numbers (0-65535)
  • 4-byte ASNs (4200000000+) cannot fit in standard communities

Solution:

  • Large Communities support full 32-bit ASNs
  • Two 32-bit values for flexible encoding
  • Total 96 bits (12 bytes)

Configuration Example

neighbor 192.168.1.1 {
    router-id 192.168.1.2;
    local-address 192.168.1.2;
    local-as 4200000000;  # 4-byte ASN
    peer-as 65000;

    family {
        ipv4 unicast;
    }

    static {
        route 10.0.0.0/8 {
            next-hop 192.168.1.2;
            large-community [ 4200000000:100:200 4200000000:100:300 ];
        }
    }
}

API Example (Large Communities)

#!/usr/bin/env python3
import sys

# Route with large communities (4-byte ASN)
route = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.2 "
    "large-community [ 4200000000:100:200 4200000000:100:300 ]"
)

sys.stdout.write(f"{route}\n")
sys.stdout.flush()

# Mix standard and large communities
mixed = (
    "announce route 172.16.0.0/12 "
    "next-hop 192.168.1.2 "
    "community [ 65001:100 ] "
    "large-community [ 4200000000:1:1 ]"
)

sys.stdout.write(f"{mixed}\n")
sys.stdout.flush()

Large Community Patterns

Geographic + Function Encoding:

4200000000:1000:1   # Region: North America, Function: Customer
4200000000:2000:1   # Region: Europe, Function: Customer
4200000000:3000:2   # Region: Asia, Function: Peer

Hierarchical Tagging:

ASN:Category:Subcategory
4200000000:100:1    # Category: Customer, Subcategory: Tier-1
4200000000:100:2    # Category: Customer, Subcategory: Tier-2
4200000000:200:1    # Category: Peer, Subcategory: IX

Well-Known Communities

Standard Well-Known Communities

NO_EXPORT (0xFFFFFF01)

Meaning: Do not advertise outside the local AS (or confederation)

Use Case: Keep routes local to your network

Example:

# Route visible only within AS 65001
route = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.2 "
    "community [ no-export ]"  # or 65535:65281
)

Behavior:

  • eBGP neighbors: Route NOT advertised
  • iBGP neighbors: Route IS advertised
  • Confederation: Route advertised within confederation

NO_ADVERTISE (0xFFFFFF02)

Meaning: Do not advertise to ANY peer (iBGP or eBGP)

Use Case: Route is local to this router only

Example:

# Route not propagated to any neighbor
route = (
    "announce route 172.16.0.0/12 "
    "next-hop 192.168.1.2 "
    "community [ no-advertise ]"  # or 65535:65282
)

Behavior:

  • eBGP neighbors: Route NOT advertised
  • iBGP neighbors: Route NOT advertised
  • Local use only

BLACKHOLE (0xFFFF029A / 65535:666)

Meaning: Traffic to this prefix should be discarded (blackholed)

Use Case: DDoS mitigation, null routing

Example:

# Blackhole attacker IP
blackhole = (
    "announce route 1.2.3.4/32 "
    "next-hop 192.0.2.1 "  # Discard next-hop
    "community [ blackhole ]"  # or 65535:666
)

Typical Workflow:

  1. Detect DDoS attack from 1.2.3.4
  2. Announce 1.2.3.4/32 with BLACKHOLE community
  3. Upstream provider discards traffic to 1.2.3.4
  4. DDoS mitigated

See: DDoS Mitigation use case


NOPEER (0xFFFFFF04)

Meaning: Do not advertise to lateral peers (only upstream/downstream)

Use Case: Control route propagation in transit networks

Example:

route = (
    "announce route 192.168.0.0/16 "
    "next-hop 192.168.1.2 "
    "community [ nopeer ]"  # or 65535:65284
)

Informational Communities (RFC 8642)

ExaBGP supports these informational well-known communities:

ACCEPT_OWN          0xFFFF0001    # Accept routes with own AS in path
ROUTE_FILTER_v4     0xFFFF0003    # Carry IPv4 route filtering
ROUTE_FILTER_v6     0xFFFF0004    # Carry IPv6 route filtering
LLGR_STALE          0xFFFF0006    # Long-lived graceful restart stale
NO_LLGR             0xFFFF0007    # Do not treat as LLGR
STANDBY_PE          0xFFFF0009    # Standby PE (EVPN)

Configuration Examples

Static Route with Communities

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

    static {
        # Route with multiple community types
        route 10.0.0.0/8 {
            next-hop 192.168.1.2;
            community [ 65001:100 65001:200 no-export ];
            large-community [ 4200000000:1:1 ];
        }

        # Blackhole route
        route 1.2.3.4/32 {
            next-hop 192.0.2.1;
            community [ blackhole ];
        }
    }
}

FlowSpec with Extended Communities

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

    flow {
        route {
            match {
                source 1.2.3.0/24;
                destination-port =80;
                protocol tcp;
            }
            then {
                discard;
            }
        }
    }
}

VPNv4 with Route Targets

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

    static {
        route 10.0.0.0/8 {
            next-hop 192.168.1.2;
            rd 65001:100;
            label 1000;
            extended-community [ target:65001:100 origin:65001:1 ];
        }
    }
}

API Usage

Text API - Standard Communities

#!/usr/bin/env python3
"""Standard communities via text API"""
import sys

# Single community
sys.stdout.write("announce route 10.0.0.0/8 next-hop 192.168.1.2 community 65001:100\n")
sys.stdout.flush()

# Multiple communities
sys.stdout.write("announce route 10.0.1.0/24 next-hop 192.168.1.2 community [ 65001:100 65001:200 ]\n")
sys.stdout.flush()

# Well-known communities
sys.stdout.write("announce route 10.0.2.0/24 next-hop 192.168.1.2 community no-export\n")
sys.stdout.flush()

# BLACKHOLE community
sys.stdout.write("announce route 1.2.3.4/32 next-hop 192.0.2.1 community blackhole\n")
sys.stdout.flush()

Text API - Extended Communities

#!/usr/bin/env python3
"""Extended communities via text API"""
import sys

# Route Target
sys.stdout.write(
    "announce route 10.0.0.0/8 next-hop 192.168.1.2 rd 65001:1 label 100 "
    "extended-community [ target:65001:100 ]\n"
)
sys.stdout.flush()

# Multiple extended communities
sys.stdout.write(
    "announce route 10.0.1.0/24 next-hop 192.168.1.2 rd 65001:1 label 101 "
    "extended-community [ target:65001:100 target:65001:200 origin:65001:1 ]\n"
)
sys.stdout.flush()

# IPv4-based Route Target
sys.stdout.write(
    "announce route 10.0.2.0/24 next-hop 192.168.1.2 rd 65001:1 label 102 "
    "extended-community [ target:192.0.2.1:100 ]\n"
)
sys.stdout.flush()

# 4-byte ASN Route Target
sys.stdout.write(
    "announce route 10.0.3.0/24 next-hop 192.168.1.2 rd 65001:1 label 103 "
    "extended-community [ target4:4200000000:100 ]\n"
)
sys.stdout.flush()

Text API - Large Communities

#!/usr/bin/env python3
"""Large communities via text API"""
import sys

# Single large community
sys.stdout.write(
    "announce route 10.0.0.0/8 next-hop 192.168.1.2 "
    "large-community 4200000000:100:200\n"
)
sys.stdout.flush()

# Multiple large communities
sys.stdout.write(
    "announce route 10.0.1.0/24 next-hop 192.168.1.2 "
    "large-community [ 4200000000:100:200 4200000000:100:300 ]\n"
)
sys.stdout.flush()

# Mix standard and large communities
sys.stdout.write(
    "announce route 10.0.2.0/24 next-hop 192.168.1.2 "
    "community [ 65001:100 no-export ] "
    "large-community [ 4200000000:1:1 ]\n"
)
sys.stdout.flush()

JSON API - Communities

#!/usr/bin/env python3
"""Communities via JSON API"""
import sys
import json

# Route with communities
route = {
    "exabgp": "5.0",
    "time": 1699564800.0,
    "neighbor": "192.168.1.1",
    "message": {
        "update": {
            "announce": {
                "ipv4 unicast": {
                    "192.168.1.2": [
                        {
                            "nlri": "10.0.0.0/8",
                            "attribute": {
                                "community": [
                                    [65001, 100],
                                    [65001, 200]
                                ],
                                "large-community": [
                                    [4200000000, 1, 1]
                                ]
                            }
                        }
                    ]
                }
            }
        }
    }
}

sys.stdout.write(json.dumps(route) + "\n")
sys.stdout.flush()

Use Cases and Patterns

1. Traffic Engineering with Communities

Scenario: Control route preference through community-based MED adjustment.

Example:

#!/usr/bin/env python3
"""Traffic engineering with community-based path selection"""
import sys

# Prefer path via ISP-1
route_isp1 = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.10 "
    "community [ 65001:100 ]"  # Tag: ISP-1
)

# Backup path via ISP-2
route_isp2 = (
    "announce route 10.0.0.0/8 "
    "next-hop 192.168.1.20 "
    "community [ 65001:200 ]"  # Tag: ISP-2 (backup)
)

sys.stdout.write(f"{route_isp1}\n")
sys.stdout.write(f"{route_isp2}\n")
sys.stdout.flush()

# Upstream applies policy:
# - Match community 65001:100 β†’ Set LOCAL_PREF 150
# - Match community 65001:200 β†’ Set LOCAL_PREF 100

Upstream router configuration (Cisco example):

route-map SET_PREF permit 10
  match community 100  ! Community-list matching 65001:100
  set local-preference 150

route-map SET_PREF permit 20
  match community 200  ! Community-list matching 65001:200
  set local-preference 100

2. DDoS Mitigation with BLACKHOLE Community

Scenario: Null-route attacker IP via BGP blackhole community.

Example:

#!/usr/bin/env python3
"""DDoS mitigation with blackhole community"""
import sys
import time

def blackhole_ip(attacker_ip):
    """Blackhole attacker IP via BGP"""
    route = (
        f"announce route {attacker_ip}/32 "
        f"next-hop 192.0.2.1 "  # RFC 5735 discard next-hop
        f"community [ blackhole ]"
    )

    sys.stdout.write(f"{route}\n")
    sys.stdout.flush()

    print(f"Blackholed {attacker_ip}", file=sys.stderr)

def unblackhole_ip(attacker_ip):
    """Remove blackhole"""
    withdraw = f"withdraw route {attacker_ip}/32"
    sys.stdout.write(f"{withdraw}\n")
    sys.stdout.flush()

    print(f"Removed blackhole for {attacker_ip}", file=sys.stderr)

# Detect attack and blackhole
attacker = "1.2.3.4"
blackhole_ip(attacker)

# Wait for attack to subside
time.sleep(300)  # 5 minutes

# Remove blackhole
unblackhole_ip(attacker)

Upstream provider action:

  • Receives route with BLACKHOLE community
  • Installs route with next-hop pointing to null0
  • Traffic to 1.2.3.4/32 is dropped at edge

3. VPN Route Target Filtering

Scenario: L3VPN route distribution using Route Target communities.

Example:

#!/usr/bin/env python3
"""L3VPN with Route Target communities"""
import sys

# Customer A VPN routes (RT: 65001:100)
def announce_customer_a_routes():
    """Announce routes for Customer A VPN"""
    routes = [
        "10.0.0.0/8",
        "172.16.0.0/12",
    ]

    for prefix in routes:
        route = (
            f"announce route {prefix} "
            f"next-hop 192.168.1.2 "
            f"rd 65001:1 "
            f"label 1000 "
            f"extended-community [ target:65001:100 ]"
        )
        sys.stdout.write(f"{route}\n")

    sys.stdout.flush()
    print("Customer A routes announced (RT: 65001:100)", file=sys.stderr)

# Customer B VPN routes (RT: 65001:200)
def announce_customer_b_routes():
    """Announce routes for Customer B VPN"""
    routes = [
        "192.168.0.0/16",
    ]

    for prefix in routes:
        route = (
            f"announce route {prefix} "
            f"next-hop 192.168.1.2 "
            f"rd 65001:2 "
            f"label 2000 "
            f"extended-community [ target:65001:200 ]"
        )
        sys.stdout.write(f"{route}\n")

    sys.stdout.flush()
    print("Customer B routes announced (RT: 65001:200)", file=sys.stderr)

announce_customer_a_routes()
announce_customer_b_routes()

# PE routers import routes matching configured Route Targets
# Customer A PE: Import RT 65001:100
# Customer B PE: Import RT 65001:200

4. Geographic Route Tagging

Scenario: Tag routes by geographic origin for policy-based routing.

Example:

#!/usr/bin/env python3
"""Geographic tagging with large communities"""
import sys

# Define geographic regions
REGIONS = {
    "us-east": 4200000000:1000:1,
    "us-west": 4200000000:1000:2,
    "eu-central": 4200000000:2000:1,
    "apac": 4200000000:3000:1,
}

def announce_regional_route(prefix, region, nexthop):
    """Announce route with geographic tag"""
    if region not in REGIONS:
        print(f"Unknown region: {region}", file=sys.stderr)
        return

    route = (
        f"announce route {prefix} "
        f"next-hop {nexthop} "
        f"large-community [ {REGIONS[region]} ]"
    )

    sys.stdout.write(f"{route}\n")
    sys.stdout.flush()

    print(f"Announced {prefix} from {region}", file=sys.stderr)

# Announce routes from different regions
announce_regional_route("10.1.0.0/16", "us-east", "10.0.1.1")
announce_regional_route("10.2.0.0/16", "eu-central", "10.0.2.1")
announce_regional_route("10.3.0.0/16", "apac", "10.0.3.1")

5. NO_EXPORT for Local Routes

Scenario: Advertise routes within AS but not to external peers.

Example:

#!/usr/bin/env python3
"""Internal-only routes with NO_EXPORT"""
import sys

# Infrastructure routes - iBGP only
internal_routes = [
    "10.0.0.0/8",      # Internal network
    "172.16.0.0/12",   # Private network
    "192.168.0.0/16",  # Management network
]

for prefix in internal_routes:
    route = (
        f"announce route {prefix} "
        f"next-hop 192.168.1.2 "
        f"community [ no-export ]"
    )
    sys.stdout.write(f"{route}\n")

sys.stdout.flush()

print("Internal routes announced with NO_EXPORT", file=sys.stderr)
# Routes visible to iBGP neighbors only
# NOT advertised to eBGP peers

Community Matching and Filtering

Receive Routes with Communities (JSON API)

#!/usr/bin/env python3
"""Filter routes based on communities"""
import sys
import json

def process_route_with_communities():
    """Process routes and filter by community"""

    while True:
        line = sys.stdin.readline().strip()
        if not line:
            break

        try:
            msg = json.loads(line)

            if msg.get('type') == 'update' and 'announce' in msg:
                for afi_safi, announcements in msg['announce'].items():
                    for nexthop, prefixes in announcements.items():
                        for prefix_data in prefixes:
                            prefix = prefix_data.get('nlri')
                            communities = prefix_data.get('attribute', {}).get('community', [])

                            # Check for specific community
                            if [65001, 100] in communities:
                                print(f"Route {prefix} has community 65001:100 - accept", file=sys.stderr)
                                # Install route

                            # Check for NO_EXPORT
                            if [0xFFFF, 0xFF01] in communities:
                                print(f"Route {prefix} has NO_EXPORT - local only", file=sys.stderr)
                                # Do not re-advertise

                            # Check for BLACKHOLE
                            if [0xFFFF, 0x029A] in communities:
                                print(f"Route {prefix} has BLACKHOLE - null route", file=sys.stderr)
                                # Install blackhole route

        except json.JSONDecodeError:
            pass

process_route_with_communities()

Community-Based Route Selection

#!/usr/bin/env python3
"""Select best path based on community"""
import sys
import json

def select_path_by_community(routes):
    """Select path with preferred community"""

    PREFER_COMMUNITIES = [
        [65001, 100],  # Highest preference
        [65001, 200],  # Medium preference
        [65001, 300],  # Lowest preference
    ]

    best_route = None
    best_priority = 999

    for route in routes:
        communities = route.get('attribute', {}).get('community', [])

        for priority, preferred in enumerate(PREFER_COMMUNITIES):
            if preferred in communities:
                if priority < best_priority:
                    best_priority = priority
                    best_route = route
                break

    return best_route

# Use in route selection logic

Common Errors and Solutions

Error 1: Community Not Propagated

Symptom: Community sent but not received by peer.

Causes:

  1. Peer strips communities on import
  2. Community filtered by peer's route-map
  3. Community type not supported by peer

Solutions:

# Verify peer configuration
# Cisco - ensure communities not removed:
router bgp 65000
  neighbor 192.168.1.2 send-community
  neighbor 192.168.1.2 send-community extended
  neighbor 192.168.1.2 send-community large

# Juniper:
protocols {
    bgp {
        group peers {
            neighbor 192.168.1.2 {
                import allow-communities;
            }
        }
    }
}

# Check ExaBGP logs
grep -i community /var/log/exabgp.log

Error 2: Invalid Community Format

Symptom: Community parsing error.

Logs:

ERROR    Invalid community format: 65001-100

Correct Formats:

# Standard community: AS:Value (colon separator)
"community 65001:100"          # Correct
"community 65001-100"          # Wrong (hyphen)

# Extended community: type:AS:Value
"extended-community target:65001:100"  # Correct
"extended-community 65001:100"         # Wrong (missing type)

# Large community: ASN:Val1:Val2
"large-community 4200000000:100:200"   # Correct
"large-community 4200000000:100"       # Wrong (missing Val2)

Error 3: Well-Known Community Not Recognized

Symptom: Well-known community syntax error.

Correct Syntax:

# Correct (lowercase, hyphen):
"community no-export"
"community no-advertise"
"community blackhole"
"community nopeer"

# Also correct (numeric):
"community 65535:65281"  # NO_EXPORT
"community 65535:65282"  # NO_ADVERTISE
"community 65535:666"    # BLACKHOLE

# Wrong:
"community NO_EXPORT"    # Wrong case
"community noexport"     # Wrong format

Error 4: Large Community Not Supported

Symptom: Large communities not recognized by peer.

Causes:

  1. Peer does not support RFC 8092
  2. Peer running old software version
  3. Large community capability not negotiated

Solutions:

# Verify peer supports large communities (2017+ software)
# Cisco IOS XR 6.0.0+, IOS XE 16.6+, NX-OS 7.0(3)I5+
# Juniper Junos 14.2+

# Check capability negotiation
grep -i "large" /var/log/exabgp.log

# Fallback to standard communities for legacy peers
# Use standard communities for 2-byte ASNs
# Use large communities only with supporting peers

See Also


References

RFCs

ExaBGP Documentation

Implementation

  • Source Code: src/exabgp/bgp/message/update/attribute/community/
  • Attribute Type Code:
    • Standard: 8
    • Extended: 16
    • Large: 32
  • ExaBGP Version: 3.x, 4.x, 5.x/main

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

Clone this wiki locally