Skip to content

[preview] Integrated routing feature branch (VRF/L3VPN/EVPN/policy/…) — not for merge - #153

Draft
gusbourg wants to merge 77 commits into
holo-routing:masterfrom
gusbourg:integration
Draft

[preview] Integrated routing feature branch (VRF/L3VPN/EVPN/policy/…) — not for merge#153
gusbourg wants to merge 77 commits into
holo-routing:masterfrom
gusbourg:integration

Conversation

@gusbourg

@gusbourg gusbourg commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Preview / not for merge. This is an integration branch combining the individually-filed feature PRs (#128–152) into one buildable tree, shared for visibility and discussion — it is not intended to be merged as a single PR. The focused PRs remain the intended contribution units.

Combined here: the bug fixes, VRF / network-instance, BGP/MPLS L3VPN (VPNv4/v6), labeled-unicast, route-reflection, the routing-policy engine (defined-sets, community/as-path/regex match+set, soft-reconfiguration), default-originate, prefix-limits, multipath/ECMP, BFD, AS-path edge knobs, and EVPN with multihoming (ES/Type-4/DF, Type-1 EAD + mass-withdraw, MAC mobility, aliasing).

Not yet folded in (they need a real port rather than mechanical conflict-resolution, tracked separately): route aggregation (aggregate-address — needs porting to the AddressFamily::Prefix model) and ADD-PATH (needs the Adj-RIB-In path-id-key reconciliation with soft-reconfiguration).

Happy to walk through any part.

🤖 Generated with Claude Code

gusbourg and others added 30 commits July 3, 2026 21:08
Two defects combined to make address-family config changes routing-inert
until the next unrelated topology event:

1. The address-family-list create/delete and enabled callbacks re-originate
   LSPs but never queue Event::RerunSpf, even though is_af_enabled() gates
   SPF vertex expansion (the dual-stack protocols-supported check).
2. Event::RerunSpf itself only fires the delay FSM's ConfigChange event;
   spf_type defaults to RouteOnly, so even when it ran, the SPT (where the
   vertex-eligibility check lives) was not recomputed.

Queue RerunSpf from the AF callbacks and make RerunSpf request a full SPF.
Observable symptom fixed: disabling ipv6 to interoperate with IPv4-only
IS-IS routers now takes effect immediately instead of after a link flap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fixes

static_nexthop_get() required an outgoing-interface: a static route
configured with only a next-hop-address produced no nexthop at all and was
silently never installed. Resolve the address against the interfaces'
connected prefixes when no interface is configured, matching expected
static-route semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MPLS (LFIB) routes were always built with RTA_MULTIPATH, which the kernel
does not accept for AF_MPLS single-nexthop routes: they installed with no
nexthop and were flagged dead/linkdown, so holo worked as an SR ingress PE
but not as a transit/egress LSR. Emit the nexthop as top-level Oif + Via +
NewDestination attributes for the single-nexthop case (verified against the
kernel with a standalone repro); the multipath encoding is retained for the
ECMP case, which has a separate kernel-side RTA_MULTIPATH/AF_MPLS issue
(iproute2 exhibits it too) tracked as remaining work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expose the IETF neighbor route-reflector container and use the client and cluster-id settings when disseminating iBGP routes. Reflected advertisements now carry ORIGINATOR_ID and CLUSTER_LIST, and received routes are rejected when ORIGINATOR_ID or CLUSTER_LIST would create a reflection loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add an AddressFamily::Prefix associated type for NLRI/RIB keys while keeping policy, northbound, and IBus boundaries on normal IP network values. IPv4 and IPv6 unicast use identity conversions, preserving current behavior.

Switch BGP RIB prefix storage from PrefixMap to BTreeMap so future address families are not constrained by prefix_trie's primitive-integer key representation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a BGP conformance topology that negotiates IPv4 labeled-unicast, imports a labeled route, and verifies both the IP route label stack and MPLS label programming outputs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Use the route reflector server cluster ID when reflecting iBGP routes, including advertisements to non-client peers, and add a conformance topology covering client reflection, cluster-loop rejection, and non-client reflection scope.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extend the labeled-unicast replay to negotiate IPv6 labeled-unicast, import a labeled IPv6 route, track its IPv6 next hop, and assert both IP route label stack and MPLS label programming outputs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First step of VRF support (Option C: IETF-native, no schema-mount). Embeds
ietf-network-instance (+ ietf-yang-schema-mount for the import) and adds:

- a deviation removing the mandatory schema-mount root-type (Holo binds by
  name, it does not mount per-instance schema) and deferring bind-ni-name
  (+ its notification) until interface-side VRF support lands;
- holo-network-instance augmentation: a 'network-instance' leafref on
  control-plane-protocol, binding a protocol instance to a VRF by name;
- the network-instance config registry (name/enabled/description) and the
  per-instance NI binding, stored on Master (consumed by later per-VRF
  routing steps).

Validated: holod boots (northbound callbacks complete), commits/round-trips
network-instances + a bound protocol, and the leafref enforces referential
integrity (binding to an unknown VRF is rejected).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…le-ids

Southbound VRF learning: holo-interface parses IFLA_MASTER (enslavement)
and the VRF device's IFLA_INFO_DATA table-id from RTM_NEWLINK, carries both
in InterfaceUpdateMsg. holo-routing records each VRF device's table-id and
resolves a matching network-instance's table-id — both when the device is
learned before the NI is configured (on NI create) and after (on
InterfaceUpd).

Exposed via a holo-network-instance:state/table-id oper-state leaf.

Validated: a network-instance bound to a kernel VRF device resolves its
table-id in both orderings (device-before-config and config-before-device).
This table-id is what per-VRF route installation programs routes into.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thread an optional kernel table id through route messages, RIB route selection, and netlink route add/delete so routes can be installed outside the main table. Instance identity now carries the configured network-instance and static route state is keyed by instance plus prefix, allowing overlapping static prefixes in different VRFs.

When a VRF table has not been resolved yet, static route installation is deferred with a warning and replayed when the matching VRF device is learned, instead of silently programming the main table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Carry the configured network-instance into protocol tasks so BGP can bind its listener and active connect sockets to the matching Linux VRF device. Route messages from VRF-bound protocol instances now inherit the resolved VRF table in routing when the protocol does not specify a table id itself.

Populate the protocol-name to network-instance mapping during create_prepare so first-transaction child config is relayed to the VRF-qualified protocol instance instead of being dropped as a default-instance change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add tests for both VRF table-id resolution orderings: creating a network-instance after its VRF device is learned, and learning the VRF device after the network-instance exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Guard UPDATE processing after FSM transitions so rejected updates cannot reach import code without a neighbor identifier, and ignore notification timestamps in test state snapshots.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Keep the optional route table-id available for VRF route programming while preserving the legacy serialized shape for default-table routes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MPLS (LFIB) routes were always built with RTA_MULTIPATH, which the kernel
does not accept for AF_MPLS single-nexthop routes: they installed with no
nexthop and were flagged dead/linkdown, so holo worked as an SR ingress PE
but not as a transit/egress LSR. Emit the nexthop as top-level Oif + Via +
NewDestination attributes for the single-nexthop case (verified against the
kernel with a standalone repro); the multipath encoding is retained for the
ECMP case, which has a separate kernel-side RTA_MULTIPATH/AF_MPLS issue
(iproute2 exhibits it too) tracked as remaining work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add L3VPN IPv4/IPv6 AFI-SAFI identities, typed route distinguisher and route-target helpers, and labeled VPN NLRI structures with MP_REACH/MP_UNREACH encode/decode support.

Advertise VPNv4/VPNv6 multiprotocol capabilities when the neighbor AF is configured, while decoded VPN updates remain explicitly ignored until the VPN RIB/import path is added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Send deterministic VPNv4 and VPNv6 labeled NLRIs after VPN AF negotiation so FRR can validate Holo's MP-BGP VPN wire encoding before the Phase C VRF export path exists.

This is temporary Phase-B scaffolding; real VPN routes will come from per-VRF export and label allocation in the L3VPN import/export implementation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add VPNv4 and VPNv6 address-family table types keyed by route distinguisher plus IP prefix, with routing tables and neighbor update queues for both VPN AFs.

Retain decoded VPN MP_REACH routes in pre-policy Adj-RIB-In and remove them on MP_UNREACH while leaving full import policy, label persistence, and VRF export/import for the next Phase C slice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the Phase-B hardcoded VPNv4 and VPNv6 updates that were sent when a VPN-capable session came up.

Real VPN routes must come from Phase-C VRF export/import and label allocation rather than session initialization.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add optional VPN label metadata to BGP Route and LocalRoute so labeled VPN NLRI can carry its label beyond packet decoding.

Store decoded VPNv4 and VPNv6 labels on pre-policy Adj-RIB-In routes while keeping RTs in the existing extended-community attribute path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Accept decoded VPN NLRI into post-policy Adj-RIB-In until the import policy path can carry RD-qualified keys.

Run VPNv4 and VPNv6 routes through NHT and decision processing while disabling kernel Loc-RIB install and generic dissemination for VPN AFs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gusbourg and others added 30 commits July 5, 2026 21:34
…tion

# Conflicts:
#	holo-protocol/src/lib.rs
# Conflicts:
#	holo-bgp/tests/conformance/topologies/mod.rs
…tion

# Conflicts:
#	holo-bgp/src/af.rs
#	holo-bgp/src/events.rs
#	holo-bgp/src/ibus/rx.rs
#	holo-bgp/src/ibus/tx.rs
#	holo-bgp/src/instance.rs
#	holo-bgp/src/neighbor.rs
#	holo-bgp/src/northbound/configuration.rs
#	holo-bgp/src/northbound/state.rs
#	holo-bgp/src/packet/attribute.rs
#	holo-bgp/src/packet/message.rs
#	holo-bgp/src/rib.rs
#	holo-bgp/tests/conformance/topologies/mod.rs
#	holo-bgp/tests/packet/update.rs
#	holo-routing/src/netlink.rs
#	holo-utils/src/bgp.rs
#	holo-yang/modules/deviations/holo-ietf-bgp-deviations.yang
…tion

# Conflicts:
#	holo-bgp/src/events.rs
#	holo-bgp/tests/conformance/topologies/mod.rs
…egration

# Conflicts:
#	holo-bgp/src/events.rs
#	holo-bgp/src/neighbor.rs
# Conflicts:
#	holo-bgp/src/events.rs
#	holo-bgp/tests/conformance/topologies/mod.rs
#	holo-protocol/src/lib.rs
#	holo-protocol/src/test/stub/mod.rs
#	holo-utils/src/bgp.rs
…gration

# Conflicts:
#	holo-bgp/src/events.rs
…ation

# Conflicts:
#	holo-bgp/src/rib.rs
#	holo-protocol/src/lib.rs
#	holo-protocol/src/test/stub/mod.rs
# Conflicts:
#	holo-bgp/src/neighbor.rs
#	holo-bgp/src/northbound/configuration.rs
#	holo-protocol/src/lib.rs
#	holo-protocol/src/test/stub/mod.rs
…tion

# Conflicts:
#	holo-bgp/src/events.rs
#	holo-bgp/src/northbound/configuration.rs
#	holo-bgp/src/rib.rs
#	holo-protocol/src/lib.rs
#	holo-protocol/src/test/stub/mod.rs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants