Support overlapping RFC6996 private ASNs per tenant #603

Closed
opened 2026-04-05 16:51:08 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @patrickpreuss on 1/13/2026

NetBox version

v4.5.0

Feature type

Data model extension

Proposed functionality

NetBox currently requires ASNs to be globally unique.

This conflicts with real-world use of RFC6996 private-use ASNs (64512–65534 and 4200000000–4294967294), which are intended for internal use and are commonly reused across separate administrative domains (e.g., customers/tenants).

Desired behavior

  • Keep global uniqueness for public ASNs (outside RFC6996 private ranges).
  • Allow duplicates for RFC6996 private ASNs when they are scoped by Tenant (or another accepted scoping object; for this proposal, “Tenant” is the scope).

Uniqueness rules:

  • If ASN is private and tenant is set → uniqueness is enforced on (tenant, asn).
  • If ASN is private and tenant is not set → treat as unscoped and enforce uniqueness on asn (prevents ambiguous “global private” duplicates).
  • If ASN is public → enforce uniqueness on asn globally (current behavior).

UI / workflow changes

On the ASN create/edit form, add help text such as:

“RFC6996 private ASNs may overlap between tenants; set a Tenant to allow reuse.”

Validation rules are the same as the uniqueness rules.

API behavior

  • No new endpoints are required.
  • Filtering by asn may return multiple results for RFC6996 private ASNs (because overlap is allowed across tenants).
  • Clients should disambiguate using tenant (or another scope filter if adopted later) or use the object id.

Interaction with ASN Ranges (optional but important)

NetBox supports allocating ASNs from ASN Ranges via REST API (“next available”).
To make tenant-scoped private ASN reuse practical for MSP-style usage:

  • Extend ASN range allocation logic to optionally accept a tenant parameter when allocating a private ASN.
  • If tenant is supplied and the ASN range is RFC6996 private → compute “next available” per tenant.
  • If no tenant is supplied → keep current behavior (global availability / unscoped allocation).

There’s already interest in overlapping ASNs in general (e.g., disabling global uniqueness). This proposal is narrower and standards-driven (RFC6996) and uses tenancy as the scoping mechanism:
https://github.com/netbox-community/netbox/issues/17133

Use case

Managed service providers / multi-tenant NetBox:
Multiple customers reuse RFC6996 private ASNs internally; NetBox should model each customer’s ASN space without forcing renumbering. Tenancy is first-class in NetBox and commonly maps to “customer”.

Lab/overlay environments:
Private ASNs are frequently reused across isolated environments; scoping by tenant preserves separation while retaining global uniqueness for public ASNs.

Database changes

Replace the single global uniqueness constraint with partial unique constraints based on RFC6996 ranges:

  • Public ASNs: unique on asn where ASN is outside RFC6996 private ranges.
  • Private ASNs with tenant: unique on (tenant, asn) where ASN is in RFC6996 private ranges and tenant IS NOT NULL.
  • Private ASNs without tenant: unique on asn where ASN is in RFC6996 private ranges and tenant IS NULL

This preserves:

  • current behavior for public ASNs,
  • controlled overlap for private ASNs across tenants,
  • and prevents ambiguous duplicates when tenant is unset.

Implementation-wise, this can follow the same general approach NetBox uses elsewhere for conditional uniqueness and scoping (e.g., patterns used in prefix-related models), i.e., a nullable scope field plus conditional/partial uniqueness constraints.

External dependencies

None

*Originally created by @patrickpreuss on 1/13/2026* ### NetBox version v4.5.0 ### Feature type Data model extension ### Proposed functionality NetBox currently requires ASNs to be globally unique. This conflicts with real-world use of RFC6996 private-use ASNs (64512–65534 and 4200000000–4294967294), which are intended for internal use and are commonly reused across separate administrative domains (e.g., customers/tenants). ### Desired behavior - Keep global uniqueness for public ASNs (outside RFC6996 private ranges). - Allow duplicates for RFC6996 private ASNs when they are scoped by Tenant (or another accepted scoping object; for this proposal, “Tenant” is the scope). **Uniqueness rules:** - If ASN is private and tenant is set → uniqueness is enforced on `(tenant, asn)`. - If ASN is private and tenant is not set → treat as unscoped and enforce uniqueness on `asn` (prevents ambiguous “global private” duplicates). - If ASN is public → enforce uniqueness on `asn` globally (current behavior). ### UI / workflow changes On the ASN create/edit form, add help text such as: > “RFC6996 private ASNs may overlap between tenants; set a Tenant to allow reuse.” Validation rules are the same as the uniqueness rules. ### API behavior - No new endpoints are required. - Filtering by `asn` may return multiple results for RFC6996 private ASNs (because overlap is allowed across tenants). - Clients should disambiguate using `tenant` (or another scope filter if adopted later) or use the object `id`. **Interaction with ASN Ranges (optional but important)** NetBox supports allocating ASNs from ASN Ranges via REST API (“next available”). To make tenant-scoped private ASN reuse practical for MSP-style usage: - Extend ASN range allocation logic to optionally accept a `tenant` parameter when allocating a private ASN. - If tenant is supplied and the ASN range is RFC6996 private → compute “next available” per tenant. - If no tenant is supplied → keep current behavior (global availability / unscoped allocation). ### Related There’s already interest in overlapping ASNs in general (e.g., disabling global uniqueness). This proposal is narrower and standards-driven (RFC6996) and uses tenancy as the scoping mechanism: https://github.com/netbox-community/netbox/issues/17133 ### Use case **Managed service providers / multi-tenant NetBox:** Multiple customers reuse RFC6996 private ASNs internally; NetBox should model each customer’s ASN space without forcing renumbering. Tenancy is first-class in NetBox and commonly maps to “customer”. **Lab/overlay environments:** Private ASNs are frequently reused across isolated environments; scoping by tenant preserves separation while retaining global uniqueness for public ASNs. ### Database changes Replace the single global uniqueness constraint with partial unique constraints based on RFC6996 ranges: - Public ASNs: unique on `asn` where ASN is outside RFC6996 private ranges. - Private ASNs with tenant: unique on `(tenant, asn)` where ASN is in RFC6996 private ranges and tenant IS NOT NULL. - Private ASNs without tenant: unique on `asn` where ASN is in RFC6996 private ranges and tenant IS NULL This preserves: - current behavior for public ASNs, - controlled overlap for private ASNs across tenants, - and prevents ambiguous duplicates when tenant is unset. Implementation-wise, this can follow the same general approach NetBox uses elsewhere for conditional uniqueness and scoping (e.g., patterns used in prefix-related models), i.e., a nullable scope field plus conditional/partial uniqueness constraints. ### External dependencies None
MrUnknownDE added the netboxtype: featurenetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxtype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: feature labels 2026-04-05 16:51:23 +02:00
Sign in to join this conversation.
No Label netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#603