From 1e637d8daca9a9cc51e294584ba5b934bc33d5a0 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Mon, 21 Sep 2026 15:45:26 -0400 Subject: [PATCH] fix(api): Widen BGPRouter nodeID to the full 16-bit uSID field BGPRouterSpec.NodeID was declared an 8-bit slot -- kubebuilder Maximum=254, with a doc comment reading "Values 0 and 255 are reserved". The uSID carrier format it encodes has always treated Node-ID as a 16-bit field at bits 49-64; galactic's uformat.NodeIDMin/NodeIDMax are 0x0001-0xDFFF (0xE000-0xFFFF is the LIB, Function space rather than Node-ID space). The CRD was simply never updated when the field widened, so the API has been rejecting three quarters of the assignable range. This blocks any allocation scheme that partitions Node-ID into sub-fields. Splitting it into a 4-bit service selector plus a 12-bit node index -- so one node can hold a tenant-delivery identity, a NAT egress shard and an edge gateway without the three colliding on the /64 that ownership is decided at -- puts the very first delivery Node-ID at 0x1001, or 4097. Against the old bound every such router failed admission outright: The BGPRouter "galactic-router" is invalid: spec.nodeID: Invalid value: 4097: spec.nodeID in body should be less than or equal to 254 Raise Maximum to 57343 (0xDFFF) to match uformat, and rewrite the doc comment to name the field's real width and the ranges the carrier format reserves. Minimum stays 1: Node-ID 0x0000 is invalid. The change is purely permissive, so no existing BGPRouter becomes invalid under it. Regenerated config/crd/ and docs/api/ via task generate. Co-Authored-By: Claude Opus 5 (1M context) --- api/v1alpha1/router_types.go | 7 ++++--- config/crd/network.datumapis.com_bgprouters.yaml | 7 ++++--- docs/api/bgp.md | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/api/v1alpha1/router_types.go b/api/v1alpha1/router_types.go index 3a58562..8c22761 100644 --- a/api/v1alpha1/router_types.go +++ b/api/v1alpha1/router_types.go @@ -64,11 +64,12 @@ type BGPRouterSpec struct { // +optional SRv6Locator string `json:"srv6Locator,omitempty"` - // NodeID is this router's 8-bit slot within its PoP's SRv6Locator block, + // NodeID is this router's 16-bit slot within its PoP's SRv6Locator block, // used for RFC 9800 NEXT-CSID compression. Unique within the PoP. - // Values 0 and 255 are reserved. + // The uSID carrier format reserves 0x0000 and 0xE000-0xFFFF (the latter is + // Function space, not Node-ID space), leaving 0x0001-0xDFFF assignable. // +kubebuilder:validation:Minimum=1 - // +kubebuilder:validation:Maximum=254 + // +kubebuilder:validation:Maximum=57343 // +optional NodeID int32 `json:"nodeID,omitempty"` diff --git a/config/crd/network.datumapis.com_bgprouters.yaml b/config/crd/network.datumapis.com_bgprouters.yaml index dcad7bd..853c2ca 100644 --- a/config/crd/network.datumapis.com_bgprouters.yaml +++ b/config/crd/network.datumapis.com_bgprouters.yaml @@ -112,11 +112,12 @@ spec: type: integer nodeID: description: |- - NodeID is this router's 8-bit slot within its PoP's SRv6Locator block, + NodeID is this router's 16-bit slot within its PoP's SRv6Locator block, used for RFC 9800 NEXT-CSID compression. Unique within the PoP. - Values 0 and 255 are reserved. + The uSID carrier format reserves 0x0000 and 0xE000-0xFFFF (the latter is + Function space, not Node-ID space), leaving 0x0001-0xDFFF assignable. format: int32 - maximum: 254 + maximum: 57343 minimum: 1 type: integer routerID: diff --git a/docs/api/bgp.md b/docs/api/bgp.md index 09871e7..ff6b7aa 100644 --- a/docs/api/bgp.md +++ b/docs/api/bgp.md @@ -781,7 +781,7 @@ _Appears in:_ | `routerID` _string_ | RouterID is a unique 32-bit identifier expressed in IPv4 dotted-decimal notation.
In an IPv6-only underlay this is a logical identifier only. | | Format: ipv4
Required: \{\}
| | `addressFamilies` _[AddressFamily](#addressfamily) array_ | AddressFamilies defines the address families this router activates. | | MinItems: 1
| | `srv6Locator` _string_ | SRv6Locator is the SRv6 locator block this router owns, expressed as an
IPv6 CIDR (e.g. "2001:db8:ff01::/48"). Individual SRv6 endpoint SIDs are
host addresses within this block. | | | -| `nodeID` _integer_ | NodeID is this router's 8-bit slot within its PoP's SRv6Locator block,
used for RFC 9800 NEXT-CSID compression. Unique within the PoP.
Values 0 and 255 are reserved. | | Maximum: 254
Minimum: 1
| +| `nodeID` _integer_ | NodeID is this router's 16-bit slot within its PoP's SRv6Locator block,
used for RFC 9800 NEXT-CSID compression. Unique within the PoP.
The uSID carrier format reserves 0x0000 and 0xE000-0xFFFF (the latter is
Function space, not Node-ID space), leaving 0x0001-0xDFFF assignable. | | Maximum: 57343
Minimum: 1
| | `listenPort` _integer_ | ListenPort is the TCP port this router listens on for incoming BGP
peer connections. Defaults to 179 (the IANA-assigned BGP port) if unset. | | Maximum: 65535
Minimum: 1
|