From bd6cbf71efbc988ff0e489fa72c62745ea51bf66 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 11 May 2026 14:54:19 +0000 Subject: [PATCH 1/2] [RS] Auto-append large communities from standard prepend communities When a peer sends standard BGP communities in the 65501/65502/65503 range (used to signal prepend once/twice/thrice), the bird2 route server import filter now automatically appends the corresponding large community using the route server's ASN as the first element. This lets a single policy toolchain handle both standard and large community variants. https://claude.ai/code/session_01HtrfR9ru1jcNPwbFET6An6 --- .../known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf | 42 +++++++++++++++++++ .../known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf | 28 +++++++++++++ .../v4/router/server/bird2/neighbors.foil.php | 16 +++++++ 3 files changed, 86 insertions(+) diff --git a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf index ed08b6ffe..17cab3bf6 100644 --- a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf +++ b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf @@ -340,6 +340,20 @@ int set allas; # RFC 8326 - facilitate Graceful BGP Session Shutdown if (65535, 0) ~ bgp_community then bgp_local_pref = 0; + # Auto-append large communities when corresponding standard communities are detected. + # Per-peer variant: a standard community of (65501|65502|65503, peer) gets the + # large community (routeserverasn, 65501|65502|65503, peer) appended. + for pair pc in bgp_community do { + if pc.asn = 65501 then bgp_large_community.add( (routeserverasn, 65501, pc.data) ); + if pc.asn = 65502 then bgp_large_community.add( (routeserverasn, 65502, pc.data) ); + if pc.asn = 65503 then bgp_large_community.add( (routeserverasn, 65503, pc.data) ); + } + # All-peers variant: a standard community of (routeserverasn, 65501|65502|65503) gets + # the large community (routeserverasn, 65501|65502|65503, 1|2|3) appended. + if (routeserverasn, 65501) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65501, 1) ); + if (routeserverasn, 65502) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65502, 2) ); + if (routeserverasn, 65503) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65503, 3) ); + # Filter small prefixes if ( net ~ [ 0.0.0.0/0{25,32} ] ) then { bgp_large_community.add( IXP_LC_FILTERED_PREFIX_LEN_TOO_LONG ); @@ -598,6 +612,20 @@ int set allas; # RFC 8326 - facilitate Graceful BGP Session Shutdown if (65535, 0) ~ bgp_community then bgp_local_pref = 0; + # Auto-append large communities when corresponding standard communities are detected. + # Per-peer variant: a standard community of (65501|65502|65503, peer) gets the + # large community (routeserverasn, 65501|65502|65503, peer) appended. + for pair pc in bgp_community do { + if pc.asn = 65501 then bgp_large_community.add( (routeserverasn, 65501, pc.data) ); + if pc.asn = 65502 then bgp_large_community.add( (routeserverasn, 65502, pc.data) ); + if pc.asn = 65503 then bgp_large_community.add( (routeserverasn, 65503, pc.data) ); + } + # All-peers variant: a standard community of (routeserverasn, 65501|65502|65503) gets + # the large community (routeserverasn, 65501|65502|65503, 1|2|3) appended. + if (routeserverasn, 65501) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65501, 1) ); + if (routeserverasn, 65502) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65502, 2) ); + if (routeserverasn, 65503) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65503, 3) ); + # Filter small prefixes if ( net ~ [ 0.0.0.0/0{25,32} ] ) then { bgp_large_community.add( IXP_LC_FILTERED_PREFIX_LEN_TOO_LONG ); @@ -771,6 +799,20 @@ int set allas; # RFC 8326 - facilitate Graceful BGP Session Shutdown if (65535, 0) ~ bgp_community then bgp_local_pref = 0; + # Auto-append large communities when corresponding standard communities are detected. + # Per-peer variant: a standard community of (65501|65502|65503, peer) gets the + # large community (routeserverasn, 65501|65502|65503, peer) appended. + for pair pc in bgp_community do { + if pc.asn = 65501 then bgp_large_community.add( (routeserverasn, 65501, pc.data) ); + if pc.asn = 65502 then bgp_large_community.add( (routeserverasn, 65502, pc.data) ); + if pc.asn = 65503 then bgp_large_community.add( (routeserverasn, 65503, pc.data) ); + } + # All-peers variant: a standard community of (routeserverasn, 65501|65502|65503) gets + # the large community (routeserverasn, 65501|65502|65503, 1|2|3) appended. + if (routeserverasn, 65501) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65501, 1) ); + if (routeserverasn, 65502) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65502, 2) ); + if (routeserverasn, 65503) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65503, 3) ); + # Filter small prefixes if ( net ~ [ 0.0.0.0/0{25,32} ] ) then { bgp_large_community.add( IXP_LC_FILTERED_PREFIX_LEN_TOO_LONG ); diff --git a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf index 35fc3a24b..820ec8499 100644 --- a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf +++ b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf @@ -374,6 +374,20 @@ int set allas; # RFC 8326 - facilitate Graceful BGP Session Shutdown if (65535, 0) ~ bgp_community then bgp_local_pref = 0; + # Auto-append large communities when corresponding standard communities are detected. + # Per-peer variant: a standard community of (65501|65502|65503, peer) gets the + # large community (routeserverasn, 65501|65502|65503, peer) appended. + for pair pc in bgp_community do { + if pc.asn = 65501 then bgp_large_community.add( (routeserverasn, 65501, pc.data) ); + if pc.asn = 65502 then bgp_large_community.add( (routeserverasn, 65502, pc.data) ); + if pc.asn = 65503 then bgp_large_community.add( (routeserverasn, 65503, pc.data) ); + } + # All-peers variant: a standard community of (routeserverasn, 65501|65502|65503) gets + # the large community (routeserverasn, 65501|65502|65503, 1|2|3) appended. + if (routeserverasn, 65501) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65501, 1) ); + if (routeserverasn, 65502) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65502, 2) ); + if (routeserverasn, 65503) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65503, 3) ); + # Filter small prefixes if ( net ~ [ ::/0{49,128} ] ) then { bgp_large_community.add( IXP_LC_FILTERED_PREFIX_LEN_TOO_LONG ); @@ -556,6 +570,20 @@ int set allas; # RFC 8326 - facilitate Graceful BGP Session Shutdown if (65535, 0) ~ bgp_community then bgp_local_pref = 0; + # Auto-append large communities when corresponding standard communities are detected. + # Per-peer variant: a standard community of (65501|65502|65503, peer) gets the + # large community (routeserverasn, 65501|65502|65503, peer) appended. + for pair pc in bgp_community do { + if pc.asn = 65501 then bgp_large_community.add( (routeserverasn, 65501, pc.data) ); + if pc.asn = 65502 then bgp_large_community.add( (routeserverasn, 65502, pc.data) ); + if pc.asn = 65503 then bgp_large_community.add( (routeserverasn, 65503, pc.data) ); + } + # All-peers variant: a standard community of (routeserverasn, 65501|65502|65503) gets + # the large community (routeserverasn, 65501|65502|65503, 1|2|3) appended. + if (routeserverasn, 65501) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65501, 1) ); + if (routeserverasn, 65502) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65502, 2) ); + if (routeserverasn, 65503) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65503, 3) ); + # Filter small prefixes if ( net ~ [ ::/0{49,128} ] ) then { bgp_large_community.add( IXP_LC_FILTERED_PREFIX_LEN_TOO_LONG ); diff --git a/resources/views/api/v4/router/server/bird2/neighbors.foil.php b/resources/views/api/v4/router/server/bird2/neighbors.foil.php index 25e4ec940..f154629cb 100644 --- a/resources/views/api/v4/router/server/bird2/neighbors.foil.php +++ b/resources/views/api/v4/router/server/bird2/neighbors.foil.php @@ -93,6 +93,22 @@ # RFC 8326 - facilitate Graceful BGP Session Shutdown if (65535, 0) ~ bgp_community then bgp_local_pref = 0; +router->bgp_lc ): ?> + # Auto-append large communities when corresponding standard communities are detected. + # Per-peer variant: a standard community of (65501|65502|65503, peer) gets the + # large community (routeserverasn, 65501|65502|65503, peer) appended. + for pair pc in bgp_community do { + if pc.asn = 65501 then bgp_large_community.add( (routeserverasn, 65501, pc.data) ); + if pc.asn = 65502 then bgp_large_community.add( (routeserverasn, 65502, pc.data) ); + if pc.asn = 65503 then bgp_large_community.add( (routeserverasn, 65503, pc.data) ); + } + # All-peers variant: a standard community of (routeserverasn, 65501|65502|65503) gets + # the large community (routeserverasn, 65501|65502|65503, 1|2|3) appended. + if (routeserverasn, 65501) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65501, 1) ); + if (routeserverasn, 65502) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65502, 2) ); + if (routeserverasn, 65503) ~ bgp_community then bgp_large_community.add( (routeserverasn, 65503, 3) ); + + # Filter small prefixes router->protocol == 6 ): ?> if ( net ~ [ ::/0{,128} ] ) then { From ae9fad8e110300436b3ad63cda522cfb6d167ebb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 11 May 2026 15:12:18 +0000 Subject: [PATCH 2/2] [RS] Recognize 65501/65502/65503 large communities for AS-path prepending Extends ixp_community_filter() so the large communities appended by the previous commit actually trigger AS-path prepending. Each existing 101/ 102/103 branch now also matches the corresponding 65501/65502/65503 variant for both per-peer and all-peers cases. https://claude.ai/code/session_01HtrfR9ru1jcNPwbFET6An6 --- data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf | 12 ++++++------ data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf | 12 ++++++------ .../v4/router/server/bird2/community-filter.foil.php | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf index 17cab3bf6..a770a2735 100644 --- a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf +++ b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv4.conf @@ -150,23 +150,23 @@ function ixp_community_filter(int peerasn) return false; # AS path prepending - if (routeserverasn, 103, peerasn) ~ bgp_large_community then { + if (routeserverasn, 103, peerasn) ~ bgp_large_community || (routeserverasn, 65503, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 102, peerasn) ~ bgp_large_community then { + } else if (routeserverasn, 102, peerasn) ~ bgp_large_community || (routeserverasn, 65502, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 101, peerasn) ~ bgp_large_community then { + } else if (routeserverasn, 101, peerasn) ~ bgp_large_community || (routeserverasn, 65501, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 103, 0) ~ bgp_large_community then { + } else if (routeserverasn, 103, 0) ~ bgp_large_community || (routeserverasn, 65503, 3) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 102, 0) ~ bgp_large_community then { + } else if (routeserverasn, 102, 0) ~ bgp_large_community || (routeserverasn, 65502, 2) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 101, 0) ~ bgp_large_community then { + } else if (routeserverasn, 101, 0) ~ bgp_large_community || (routeserverasn, 65501, 1) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); } diff --git a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf index 820ec8499..b6deed3d3 100644 --- a/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf +++ b/data/ci/known-good/ci-apiv4-b2-rs1-lan1-ipv6.conf @@ -159,23 +159,23 @@ function ixp_community_filter(int peerasn) return false; # AS path prepending - if (routeserverasn, 103, peerasn) ~ bgp_large_community then { + if (routeserverasn, 103, peerasn) ~ bgp_large_community || (routeserverasn, 65503, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 102, peerasn) ~ bgp_large_community then { + } else if (routeserverasn, 102, peerasn) ~ bgp_large_community || (routeserverasn, 65502, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 101, peerasn) ~ bgp_large_community then { + } else if (routeserverasn, 101, peerasn) ~ bgp_large_community || (routeserverasn, 65501, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 103, 0) ~ bgp_large_community then { + } else if (routeserverasn, 103, 0) ~ bgp_large_community || (routeserverasn, 65503, 3) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 102, 0) ~ bgp_large_community then { + } else if (routeserverasn, 102, 0) ~ bgp_large_community || (routeserverasn, 65502, 2) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 101, 0) ~ bgp_large_community then { + } else if (routeserverasn, 101, 0) ~ bgp_large_community || (routeserverasn, 65501, 1) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); } diff --git a/resources/views/api/v4/router/server/bird2/community-filter.foil.php b/resources/views/api/v4/router/server/bird2/community-filter.foil.php index 91642f11b..ab30faf84 100644 --- a/resources/views/api/v4/router/server/bird2/community-filter.foil.php +++ b/resources/views/api/v4/router/server/bird2/community-filter.foil.php @@ -46,23 +46,23 @@ function ixp_community_filter(int peerasn) router->bgp_lc ): ?> # AS path prepending - if (routeserverasn, 103, peerasn) ~ bgp_large_community then { + if (routeserverasn, 103, peerasn) ~ bgp_large_community || (routeserverasn, 65503, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 102, peerasn) ~ bgp_large_community then { + } else if (routeserverasn, 102, peerasn) ~ bgp_large_community || (routeserverasn, 65502, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 101, peerasn) ~ bgp_large_community then { + } else if (routeserverasn, 101, peerasn) ~ bgp_large_community || (routeserverasn, 65501, peerasn) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 103, 0) ~ bgp_large_community then { + } else if (routeserverasn, 103, 0) ~ bgp_large_community || (routeserverasn, 65503, 3) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 102, 0) ~ bgp_large_community then { + } else if (routeserverasn, 102, 0) ~ bgp_large_community || (routeserverasn, 65502, 2) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); bgp_path.prepend( bgp_path.first ); - } else if (routeserverasn, 101, 0) ~ bgp_large_community then { + } else if (routeserverasn, 101, 0) ~ bgp_large_community || (routeserverasn, 65501, 1) ~ bgp_large_community then { bgp_path.prepend( bgp_path.first ); }