Skip to content

bgpd: Allow overriding "remote-as" per-neighbor - #21450

Merged
donaldsharp merged 3 commits into
FRRouting:masterfrom
opensourcerouting:fix/bgp_peer-group_remote_as_different
Apr 6, 2026
Merged

bgpd: Allow overriding "remote-as" per-neighbor#21450
donaldsharp merged 3 commits into
FRRouting:masterfrom
opensourcerouting:fix/bgp_peer-group_remote_as_different

Conversation

@ton31337

@ton31337 ton31337 commented Apr 3, 2026

Copy link
Copy Markdown
Member

Related: #21397

@frrbot frrbot Bot added bgp tests Topotests, make check, etc labels Apr 3, 2026
@greptile-apps

greptile-apps Bot commented Apr 3, 2026

Copy link
Copy Markdown

Greptile Summary

This PR allows BGP peer-group members to override remote-as on a per-neighbor basis, addressing FRRouting issue #21397. Previously, setting remote-as on a peer-group member was rejected with BGP_ERR_PEER_GROUP_MEMBER. The implementation introduces PEER_FLAG_REMOTE_AS in peer->flags_override to track overrides, guards peer->as in peer_group2peer_config_copy, skips override peers during group remote-as propagation/deletion, and fixes the config write order so peer-group assignment is emitted before any per-peer remote-as.

Key changes:

  • bgpd/bgpd.c: Removes the BGP_ERR_PEER_GROUP_MEMBER guard in peer_remote_as, adds PEER_FLAG_REMOTE_AS tracking, guards peer->as copy in peer_group2peer_config_copy, and skips override peers in peer_group_remote_as / peer_group_remote_as_delete. Also removes the return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT in peer_group_bind to allow type-mixed binding.
  • bgpd/bgp_vty.c: Rewrites bgp_config_write_peer_global to emit neighbor X peer-group PG first (required for correct config reload) and then the per-peer remote-as when it differs from the group's.
  • bgpd/bgpd.h: Adds PEER_FLAG_REMOTE_AS (1ULL << 48) and removes the now-unused BGP_ERR_PEER_GROUP_MEMBER and BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT error codes.
  • New topotest (bgp_peer_group_remote_as_override): Validates convergence with one peer using remote-as <specific-ASN> override and another using remote-as external override.

Confidence Score: 4/5

Safe to merge with two minor style issues; core logic, flag tracking, and config write ordering are all correct.

The main logic is sound: PEER_FLAG_REMOTE_AS correctly gates peer->as in peer_group2peer_config_copy, peer_group_remote_as and peer_group_remote_as_delete correctly skip override peers, and the VTY config write is fixed to the proper ordering for reload. Two P2 items remain: a dead *as = peer->as assignment in peer_group_bind (the return it fed was removed), and a missing comment explaining why as_type does not need guarding alongside as. Neither blocks correctness or merge.

bgpd/bgpd.c β€” specifically peer_group_bind (dead output param) and peer_group2peer_config_copy (undocumented as_type behavior)

Important Files Changed

Filename Overview
bgpd/bgpd.c Core logic change: removes peer-group remote-as restriction, adds PEER_FLAG_REMOTE_AS override tracking, and guards peer->as in peer_group2peer_config_copy. One dead-code leftover in peer_group_bind after removing the error return.
bgpd/bgp_vty.c Config write order corrected: peer-group assignment now precedes per-peer remote-as, fixing config reload correctness. Condition updated to emit per-peer remote-as whenever it differs from group's (not just when group is AS_UNSPECIFIED).
bgpd/bgpd.h Adds PEER_FLAG_REMOTE_AS at bit 48 (within uint64_t range); removes BGP_ERR_PEER_GROUP_MEMBER (-4) and BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT (-8) error codes consistently.
tests/topotests/bgp_peer_group_remote_as_override/test_bgp_peer_group_remote_as_override.py New topotest verifying both AS_SPECIFIED and AS_EXTERNAL per-peer remote-as overrides converge correctly on r1. Well-structured test following existing topotest patterns.
tests/topotests/bgp_peer_group_remote_as_override/r1/frr.conf r1 configures peer-group PG with remote-as 65000, then overrides to 65002 for 192.168.1.2 and to external for 192.168.1.3 β€” correctly exercises both override types.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: bgpd/bgpd.c
Line: 3536-3539

Comment:
**Dead output parameter assignment after error return removal**

After the `return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT` was removed, the `if (as) *as = peer->as;` assignment on the preceding line is now effectively dead code. In the type-mismatch path (`gtype != BGP_PEER_INTERNAL && gtype != ptype`), the assignment was only meaningful as context for the caller to surface an error message β€” but without the error return the caller never inspects `*as` for this purpose. The function continues to bind the peer successfully regardless.

Consider removing the dead assignment or adding a comment explaining why it's retained:

```suggestion
			if ((gtype != BGP_PEER_INTERNAL) && (gtype != ptype)) {
			}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: bgpd/bgpd.c
Line: 3124-3126

Comment:
**`as_type` is not guarded alongside `as` β€” worth a comment**

The new guard correctly prevents the group's `conf->as` from overwriting the peer's AS when `PEER_FLAG_REMOTE_AS` is set. However, `peer->as_type` is not explicitly copied anywhere in `peer_group2peer_config_copy`, so it's implicitly protected already (the peer's `as_type` set by `peer_as_change()` in `peer_remote_as()` is preserved naturally). This is correct but non-obvious. A brief comment noting that `as_type` is intentionally not propagated here would help future readers:

```suggestion
	/* remote-as: propagate group AS to peer unless the peer has an
	 * explicit per-peer override.  Note: as_type is not copied here
	 * (peer_as_change owns it), so no guard is needed for it.
	 */
	if (conf->as && !CHECK_FLAG(peer->flags_override, PEER_FLAG_REMOTE_AS))
		peer->as = conf->as;
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (4): Last reviewed commit: "bgpd: Always print peer-group first for ..." | Re-trigger Greptile

@ton31337
ton31337 force-pushed the fix/bgp_peer-group_remote_as_different branch 4 times, most recently from b017878 to 0c4d42a Compare April 3, 2026 11:17
ton31337 added 3 commits April 3, 2026 14:40
Since we have a way to specify "remote-as auto", it makes sense to relax this
behavior to allow overriding remote-as for an arbitrary neighbor too.

E.g. Arista allows this behavior.

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
Avoid such a case like below where neighbor X does not have remote-as 1, but
gets the remote-as from peer-group G.

neighbor G peer-group
neighbor G remote-as 2
neighbor X remote-as 1
neighbor X peer-group G

Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>
@ton31337
ton31337 force-pushed the fix/bgp_peer-group_remote_as_different branch from 14e40f3 to d4a8cb4 Compare April 3, 2026 11:40
@donaldsharp
donaldsharp merged commit 5cf6364 into FRRouting:master Apr 6, 2026
21 checks passed
@ton31337
ton31337 deleted the fix/bgp_peer-group_remote_as_different branch April 6, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bgp master size/L tests Topotests, make check, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants