feat(fib): per-class maximum_paths_ebgp / maximum_paths_ibgp (ADR-0066)#263
Merged
Conversation
Add per-table `[[fib_tables]].maximum_paths_ebgp` and `maximum_paths_ibgp` (FRR's `maximum-paths` / `maximum-paths ibgp`): cap eBGP and iBGP equal-cost groups independently. They coexist with the overall `maximum_paths` — a per-class value overrides it for that class, and an unset class falls back to `maximum_paths` then `1`, so existing configs are byte-for-byte unchanged. The equal-cost group is homogeneous, so the best route's class (`Route::is_ebgp`) selects the cap; the re-cap moves into the per-candidate projection loop (`src/fib.rs`), and `max_install_paths` widens the RIB gather to the max of all three caps so projection can reach any per-class width. Validation applies the same `>= 1` / `<= 256` guardrail to all three (refactored into one helper). No new interop: per-class only changes which cap applies, not the kernel RTA_MULTIPATH install path (covered by M50). Tests: projection per-class cap + fallback (eBGP/iBGP), config round-trip, validation rejects 0 / over-cap for the new fields. Docs: CONFIGURATION (also backfills the missing maximum_paths row), COMPARISON footnote, CHANGELOG.
There was a problem hiding this comment.
Pull request overview
Adds per-class ECMP width caps to FIB table configuration so eBGP and iBGP equal-cost groups can be installed with different maximum path counts, while preserving existing behavior when unset.
Changes:
- Introduces
[[fib_tables]].maximum_paths_ebgpandmaximum_paths_ibgpwith shared validation guardrails (>= 1,<= 256). - Applies per-class capping during FIB projection and widens RIB candidate gathering to the maximum of overall/per-class caps.
- Adds/updates unit tests and updates configuration/docs/changelog to describe the new knobs.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/fib.rs | Adds per-class max-path selection during projection and projection tests. |
| src/fib_runtime.rs | Widens RIB gather width to cover overall and per-class caps. |
| src/config/validation.rs | Refactors ECMP cap validation into a shared helper and validates new fields. |
| src/config/tests.rs | Adds parsing/guardrail tests for the new per-class fields. |
| src/config/schema.rs | Extends FibTableConfig schema with new per-class ECMP cap fields and docs. |
| docs/CONFIGURATION.md | Documents maximum_paths plus new per-class ECMP cap fields. |
| docs/COMPARISON.md | Updates multipath feature comparison text to reflect per-class caps availability. |
| CHANGELOG.md | Adds changelog entry describing per-class ECMP caps and semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
338
to
355
| /// Project configured FIB tables and Loc-RIB install candidates using the | ||
| /// current RIB peer-group map for table allow-list checks. | ||
| #[must_use] | ||
| /// Per-class ECMP width: the eBGP/iBGP override if set, else the table's overall | ||
| /// `maximum_paths`, else 1 (today's single-next-hop behavior). The equal-cost | ||
| /// group is homogeneous, so the best route's class selects the cap. | ||
| fn per_class_max_paths(table: &FibTableConfig, is_ebgp: bool) -> usize { | ||
| if is_ebgp { | ||
| table.maximum_paths_ebgp.or(table.maximum_paths) | ||
| } else { | ||
| table.maximum_paths_ibgp.or(table.maximum_paths) | ||
| } | ||
| .unwrap_or(1) | ||
| .max(1) as usize | ||
| } | ||
|
|
||
| pub(crate) fn project_fib_intent_with_peer_groups( | ||
| tables: &[FibTableConfig], |
The per_class_max_paths helper was inserted between the doc comment / #[must_use] and project_fib_intent_with_peer_groups, so the projection function lost its documentation and must-use lint while the helper was mis-documented as doing projection. Move the helper above the doc block so each attribute lands on its intended function.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ECMP follow-up 2/4 — per-class
maximum_paths_ebgp/maximum_paths_ibgp(ADR-0066)Adds per-table per-class ECMP caps, FRR's
maximum-paths/maximum-paths ibgp:eBGP and iBGP equal-cost groups can carry different install widths.
Semantics (coexist, non-breaking)
maximum_pathsfor that class.maximum_paths, then1— so existing configs are byte-for-byte unchanged.Route::is_ebgp) selects the cap.Change
[[fib_tables]].maximum_paths_ebgp/maximum_paths_ibgpconfig + validation (same>= 1/<= 256guardrail, refactored into one helper).src/fib.rs,per_class_max_paths).max_install_pathswidens the RIB gather tomax(maximum_paths, maximum_paths_ebgp, maximum_paths_ibgp)across tables, so projection can reach any per-class width.Tests
maximum_paths_ebgp_caps_ebgp_group,maximum_paths_ibgp_caps_ibgp_group,per_class_overrides_with_maximum_paths_fallback(projection).fib_tables_per_class_maximum_paths_round_trip+ per-class cases infib_tables_reject_invalid_guardrails(0 / over-cap).No new interop: per-class only changes which cap applies, not the kernel
RTA_MULTIPATHinstall path itself (covered by M50). Docs:CONFIGURATION.md(also backfills the previously-missing
maximum_pathsrow),COMPARISON.mdfootnote,
CHANGELOG.md.Next: Link Bandwidth ext-community parse (PR3), then weighted/unequal-cost multipath (PR4, + ADR).