fix: continuing ipv6 effort, part 3: make the allocator family-aware#217
Merged
chet merged 1 commit intoNVIDIA:mainfrom Feb 10, 2026
Merged
fix: continuing ipv6 effort, part 3: make the allocator family-aware#217chet merged 1 commit intoNVIDIA:mainfrom
chet merged 1 commit intoNVIDIA:mainfrom
Conversation
Continuing the [IPv6 support](NVIDIA/bare-metal-manager-core#84) work. This is the third PR. Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout. - Accepting IPv6 site prefixes and network segments. And today: adding IPv6 support to IP address allocation. Similar to the previous PRs, this does NOT enable IPv6 support (i.e. there won't be any `DHCPv6` traffic coming in yet), but this DOES contribute to the foundational work of supporting IPv6. Eventually, we'll be able to start actually accepting requests and config for using IPv6, but there's a lot of backend work that needs to be done to get there. Trying to take it a layer at a time, and pieces of each layer at that. This is PR #3 of what is going to be many. In any case, as mentioned, this PR is focused on adding IPv6 support to address allocation, specifically the `IpAllocator`, which is being made IPv6-capable by removing all IPv4-only guards, [re]introducing `AddressSelectionStrategy` to cleanly drive allocation behavior, and unblocking IPv6 allocation across all code paths, including: - Machine interfaces (underlay). - Instance addresses (tenant/overlay) The goal is to prepare the allocation layer so that when DHCPv6 is added later, everything beneath it already works -- existing deployments and config are unaffected, as existing config is all parsed as IPv4 and uses [the same] IPv4 code paths and allocation strategies (which are verified with both existing AND new tests). One of the particularly exciting highlights here is starting to use the `AddressSelectionStrategy` for *something*. Previously, we just passed around `AddressSelectionStrategy::Automatic` for *everything*. Now, we actually use it for address selection, by saying how we want to select the next IP. - `::NextAvailableIp` is synonymous with `::Automatic` -- we pick the next `/32` or `/128` depending on the address family. - `::NextAvailablePrefix(uint)` gives us support for allocating a prefix that is wider than `/32` or `/128`. This allowed us to remove the `prefix_length` from the `IpAllocator` constructor. I was never fully happy with it being there. It seemed to make sense at the time, but it also seemed like there was something better we could do. Making it a part of `AddressSelectionStrategy` is actually what should have happened to begin with. It's also worth noting the SQL `next_machine_interface_v4_ip` fast-path got removed here. It was a nice idea to have, but it didn't play well with dual-stacking interfaces (it actually got rid of dual stack support entirely when it was introduced), and it was only ever going to support IPv4. If we have performance concerns about quickly allocating many machines, we can definitely revisit it, but unfortunately it won't work as-is for now. The previous logic has been put back, with some enhancements for dual stacking. Some callouts around backwards compatibility (in addition to tests): **DHCP is still IPv4-only** `carbide-dhcp` speaks DHCPv4 exclusively — it parses `Ipv4Addr::from_str(&forge_response.address)` on the response and calls `set_yiaddr(allocated_address)`. Even if a tenant segment is configured to support IPv6 prefixes, the DHCP server will never request an IPv6 lease. The allocator is ready, but the trigger isn't there yet. **Machine interface (underlay) IPv4 AND IPv6 work end-to-end** If an operator configures an underlay/admin segment with IPv6 prefixes, `machine_interface::create()` will allocate IPv6 addresses via the `IpAllocator`. The hostname generation, DB writes, and uniqueness constraints all work correctly, in addition to IPv4 continuing to work (using the SQL-based IPv4 allocator when relevant). **Existing IPv4 behavior is untouched** Again, `NextAvailableIp` resolves to `/32` for IPv4 — identical to the old hardcoded `prefix_length: 32`. All existing IPv4 unit and integration tests continue to pass unmodified. Tests added: | Test Name | Purpose | | --------- | ------- | | `test_ip_allocation_ipv6` | IPv6 /112 prefix allocates a /128 correctly and respects reserved addresses. | | `test_ipv6_allocation_single_address` | Allocates from /112 correctly w/ reserved and used IPs + verifies correct skip to `::4`. | | `test_ipv6_num_free_capped` | `num_free()` caps at `u32::MAX` for large IPv6 prefixes (/64). | | `test_ipv6_build_allocated_networks` | Gateway, reserved, network/broadcast exclusions all use /128 for IPv6. | | `test_address_to_hostname_v4` | Ensures IPv4 hostname formatting unchanged. | | `test_address_to_hostname_v6` | Ensures IPv6 hostname formatting is expanded to full form with dashes. | | `test_address_to_hostname_v6_loopback` | Ensures `::1` correctly expands to `0000-0000-...-0001`. | | `test_next_machine_interface_v4_ip` | Ensures existing IPv4 SQL fast-path still works. | | `test_machine_interface_create_with_ipv6_prefix` | Full end-to-end: creates underlay segment with IPv6 /112, allocates two machine interfaces, verifies sequential IPv6 addresses and correct hostnames. | Tests updated: - `test_ip_allocation_ipv4_and_6` - `test_get_network_size` Signed-off-by: Chet Nichols III <chetn@nvidia.com>
bcavnvidia
approved these changes
Feb 10, 2026
Contributor
bcavnvidia
left a comment
There was a problem hiding this comment.
Would be cool if instances would get a /64 or maybe if we could control the v6 prefix size they get.
Contributor
Author
Ohh yeah -- totally. Like, |
10 tasks
bcavnvidia
reviewed
Feb 11, 2026
| // a /30 for a tenant instance (or, at least, something other than | ||
| // a /32). For now, hard-code 32 as the length -- the plan is to | ||
| // update the InstanceInterfaceConfig to request the prefix_length. | ||
| // TODO(chet): FNN will need to override prefix_length (e.g. /30 |
chet
added a commit
that referenced
this pull request
Feb 11, 2026
## Description This PR generalizes the VPC prefix allocator from `IPv4PrefixAllocator` to `PrefixAllocator`, enabling it to work with both IPv4 and IPv6; it removes the explicit IPv6 rejection guards that we had in place in the instance allocation path. It is the next PR in a series focused on enabling IPv6 support to Carbide (tracked in [#84](#84)) For context, The VPC prefix allocator carves small subnets (FNN "linknets") out of a larger VPC prefix and assigns them to network segments during instance provisioning. Previously, it was entirely hardcoded to IPv4 types (`Ipv4Addr`, `Ipv4Network`, and `u32` arithmetic). With this PR, it has been generalized to `IpAddr` and `IpNetwork`, with new `u128` arithmetic added to support both IPv4 and IPv6. This is a very similar approach taken for the `IpAllocator` work that was done in [#217](#217), where we made the `IpAllocator` family-aware as well. Primary changes to turn this into a `PrefixAllocator` include: - The aforementioned `IpNetwork` and `IpAddr` changes (e.g. `Ip4Network::new(addr, prefix)` simply becomes `IpNetwork::new(addr, prefix)`). - The aforementioned `u128` arithmetic changes, which is now the uniform mechanism for doing math for addressing. - Introducing a simple `max_prefix_bits()` to be the family-aware replacement for `MAX_PREFIX_LEN`. - Introducing a simple `networks_overlap()` to be the family-aware replacement for `.overlaps()`. - `total_network_possible` becomes `u128` instead of `u32`. Additional changes include: - `PrefixIterator` now operates against a `u128` instead of an `Ipv4Addr`. - `get_next_usable_address` now uses `IpAddr` and `IpNetwork` with `u128` arithmetic. - Gateway assignment is now family aware. Since IPv6 uses RAs, we won't set one. - `allocate_network()` now naturally extracts an `IpNetwork` of whatever the family is. - FNN "linknet" prefix length is family aware: - IPv4 (/31) -- RFC 3021 ("Using 31-Bit Prefixes on IPv4 Point-to-Point Links") - IPv6 (/127) -- RFC 6164 ("Using 127-Bit IPv6 Prefixes on Inter-Router Links") - Added `total_linknet_segments` and `available_linknet_segments` stats (which can also be displayed in the admin CLI) -- this is to work on deprecating the `total_31_segments` and `available_31_segments`, but I don't remove them yet. **Considerations** 1. There's probably something we could do to make `PrefixAllocator` generic over an address type/family trait, but it seemed better to do `u128` arithmetic, since we can use the same arithmetic for both families without needing a trait, e.g. - IPv6 addresses are of course native `u128`. - IPv4 addresses upcast to `u128`. - All bit-shifting, comparison, and wrapping logic works identically. - We're already doing similar work in `ip_allocator.rs`. 2. Introducing `networks_overlap()` could have also been turned into a family-aware match on `Ipv4Network.overlaps()` or `Ipv6Network.overlaps()` (since there's not one that exists for `IpNetwork.overlaps()`, but I ended up doing this instead. If we want we could do the other way. The following tests were added: | Test | Address Family | Description | |------|----------------|-------------| | `test_next_iter` | IPv4 | `/31` subnets step through `/29` VPC prefix correctly. | | `test_next_iter_overflow` | IPv4 | `/31` in `/30` wraps after 2 subnets. | | `test_next_iter_ipv6` | IPv6 | `/127` subnets step through `/120` VPC prefix (`fd00::100/120`). | | `test_next_iter_ipv6_wrap_around` | IPv6 | `/127` in `/126` wraps after 2 subnets. | | `test_next_iter_ipv6_with_last_used` | IPv6 | Iterator resumes after `last_used_prefix`, skipping already-allocated subnet. | ...and the existing `PrefixAllocator` tests were also updated to confirm IPv4 behavior is unchanged. Signed-off-by: Chet Nichols III <chetn@nvidia.com> ## Type of Change <!-- Check one that best describes this PR --> - [x] **Add** - New feature or capability - [ ] **Change** - Changes in existing functionality - [x] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [x] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Related Issues (Optional) #84 ## Breaking Changes - [ ] This PR contains breaking changes <!-- If checked above, describe the breaking changes and migration steps --> ## Testing <!-- How was this tested? Check all that apply --> - [x] Unit tests added/updated - [x] Integration tests added/updated - [ ] Manual testing performed - [ ] No testing required (docs, internal refactor, etc.) ## Additional Notes <!-- Any additional context, deployment notes, or reviewer guidance --> Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 18, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84) work. Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). This PR is a little less exciting, and removes a few additional `"if ip.is_ipv6()"` guards at the API layer. With the previous PRs in place to make the backend support dual stack environments, these guards are no longer needed: the downstream code (such as database queries and instance lookups) all work with `IpAddr` and `inet` columns natively.* *Note: The DPA overlay/underlay guards in `dhcp/discover.rs` are **intentionally kept** here -- DPA will, for the foreseeable future, only support IPv4, because the Algo IP mechanism, and our inference of an underlay IP based on the `giaddr`, is IPv4 only; we don't even know how it will support IPv6 yet.* Changes here include: - Removed the IPv6 guard in the address finder `search()` function -- you can search IPv6 addresses for `StaticData`, `ResourcePools`, InstanceAddresses`, `MachineAddresses`, `BmcIp`, `ExploredEndpoint`, `LoopbackIp`, `NetworkSegment`, `RouteServers`, and `DpaAddresses` (even though DPA won't have an IPv6 address). The match on `NetworkSegment` did get small tweak -- it was hard-coded to `/32`, for single interfaces, so now it will do `/32` or `/128`. In practice, and as we get closer with IPv6, I'm not sure what prefix we'll allocate to single interfaces, so the `/128` will probably change here. - Removed the IPv6 guard from `get_cloud_init_instructions()` -- all of the downstream code from here is dual stack and supports IPv6. BUT, I did leave a note that, even though everything downstream is IPv6-capable, that it doesn't really mean much until we integrate DHCPv6 support to actually hand out IPv6 addresses, which once we do it, things should "just work". - A small tweak in `admin-cli` tests around parsing IP addresses. Just made it support IPv6. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 18, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84) work. Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). This PR is a little less exciting, and removes a few additional `"if ip.is_ipv6()"` guards at the API layer. With the previous PRs in place to make the backend support dual stack environments, these guards are no longer needed: the downstream code (such as database queries and instance lookups) all work with `IpAddr` and `inet` columns natively.* *Note: The DPA overlay/underlay guards in `dhcp/discover.rs` are **intentionally kept** here -- DPA will, for the foreseeable future, only support IPv4, because the Algo IP mechanism, and our inference of an underlay IP based on the `giaddr`, is IPv4 only; we don't even know how it will support IPv6 yet.* Changes here include: - Removed the IPv6 guard in the address finder `search()` function -- you can search IPv6 addresses for `StaticData`, `ResourcePools`, InstanceAddresses`, `MachineAddresses`, `BmcIp`, `ExploredEndpoint`, `LoopbackIp`, `NetworkSegment`, `RouteServers`, and `DpaAddresses` (even though DPA won't have an IPv6 address). The match on `NetworkSegment` did get small tweak -- it was hard-coded to `/32`, for single interfaces, so now it will do `/32` or `/128`. In practice, and as we get closer with IPv6, I'm not sure what prefix we'll allocate to single interfaces, so the `/128` will probably change here. - Removed the IPv6 guard from `get_cloud_init_instructions()` -- all of the downstream code from here is dual stack and supports IPv6. BUT, I did leave a note that, even though everything downstream is IPv6-capable, that it doesn't really mean much until we integrate DHCPv6 support to actually hand out IPv6 addresses, which once we do it, things should "just work". - A small tweak in `admin-cli` tests around parsing IP addresses. Just made it support IPv6. - Improve how we determine interface prefix lengths -- instead of just hard-coding values for IPv4 or IPv6, I'm seeing if we can get some mileage out of the `IdentifyAddressFamily` trait that we have hanging out, with an `.interface_prefix_len()` function on that. I had also considered an `InterfacePrefix` enum with `InterfacePrefix::Ipv4` and `InterfacePrefix::Ipv6`, but kept going back and forth. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 18, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84) work. Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). This PR is a little less exciting, and removes a few additional `"if ip.is_ipv6()"` guards at the API layer. With the previous PRs in place to make the backend support dual stack environments, these guards are no longer needed: the downstream code (such as database queries and instance lookups) all work with `IpAddr` and `inet` columns natively.* *Note: The DPA overlay/underlay guards in `dhcp/discover.rs` are **intentionally kept** here -- DPA will, for the foreseeable future, only support IPv4, because the Algo IP mechanism, and our inference of an underlay IP based on the `giaddr`, is IPv4 only; we don't even know how it will support IPv6 yet.* Changes here include: - Removed the IPv6 guard in the address finder `search()` function -- you can search IPv6 addresses for `StaticData`, `ResourcePools`, InstanceAddresses`, `MachineAddresses`, `BmcIp`, `ExploredEndpoint`, `LoopbackIp`, `NetworkSegment`, `RouteServers`, and `DpaAddresses` (even though DPA won't have an IPv6 address). The match on `NetworkSegment` did get small tweak -- it was hard-coded to `/32`, for single interfaces, so now it will do `/32` or `/128`. In practice, and as we get closer with IPv6, I'm not sure what prefix we'll allocate to single interfaces, so the `/128` will probably change here. - Removed the IPv6 guard from `get_cloud_init_instructions()` -- all of the downstream code from here is dual stack and supports IPv6. BUT, I did leave a note that, even though everything downstream is IPv6-capable, that it doesn't really mean much until we integrate DHCPv6 support to actually hand out IPv6 addresses, which once we do it, things should "just work". - A small tweak in `admin-cli` tests around parsing IP addresses. Just made it support IPv6. - Improve how we determine interface prefix lengths -- instead of just hard-coding values for IPv4 or IPv6, I'm seeing if we can get some mileage out of the `IdentifyAddressFamily` trait that we have hanging out, with an `.interface_prefix_len()` function on that. I had also considered an `InterfacePrefix` enum with `InterfacePrefix::Ipv4` and `InterfacePrefix::Ipv6`, but kept going back and forth. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
that referenced
this pull request
Feb 18, 2026
## Description Continuing to chip away at [IPv6 support](#84) work. Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([#192](#192)). - Accepting IPv6 site prefixes and network segments. ([#204](#204)). - Making the IP allocator family-aware ([#217](#217)). - Making the prefix allocator family-aware ([#237](#237)). This PR is a little less exciting, and removes a few additional `"if ip.is_ipv6()"` guards at the API layer. With the previous PRs in place to make the backend support dual stack environments, these guards are no longer needed: the downstream code (such as database queries and instance lookups) all work with `IpAddr` and `inet` columns natively.* *Note: The DPA overlay/underlay guards in `dhcp/discover.rs` are **intentionally kept** here -- DPA will, for the foreseeable future, only support IPv4, because the Algo IP mechanism, and our inference of an underlay IP based on the `giaddr`, is IPv4 only; we don't even know how it will support IPv6 yet.* Changes here include: - Removed the IPv6 guard in the address finder `search()` function -- you can search IPv6 addresses for `StaticData`, `ResourcePools`, `InstanceAddresses`, `MachineAddresses`, `BmcIp`, `ExploredEndpoint`, `LoopbackIp`, `NetworkSegment`, `RouteServers`, and `DpaAddresses` (even though DPA won't have an IPv6 address). The match on `NetworkSegment` did get small tweak -- it was hard-coded to `/32`, for single interfaces, so now it will do `/32` or `/128`. In practice, and as we get closer with IPv6, I'm not sure what prefix we'll allocate to single interfaces, so the `/128` will probably change here. - Removed the IPv6 guard from `get_cloud_init_instructions()` -- all of the downstream code from here is dual stack and supports IPv6. BUT, I did leave a note that, even though everything downstream is IPv6-capable, that it doesn't really mean much until we integrate DHCPv6 support to actually hand out IPv6 addresses, which once we do it, things should "just work". - A small tweak in `admin-cli` tests around parsing IP addresses. Just made it support IPv6. Signed-off-by: Chet Nichols III <chetn@nvidia.com> ## Type of Change <!-- Check one that best describes this PR --> - [x] **Add** - New feature or capability - [x] **Change** - Changes in existing functionality - [ ] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [x] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Related Issues (Optional) <!-- If applicable, provide GitHub Issue. --> ## Breaking Changes - [ ] This PR contains breaking changes <!-- If checked above, describe the breaking changes and migration steps --> ## Testing <!-- How was this tested? Check all that apply --> - [x] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] No testing required (docs, internal refactor, etc.) ## Additional Notes <!-- Any additional context, deployment notes, or reviewer guidance --> Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 18, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84)! Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). So, *this* PR enables end-to-end `AAAA` record support (for IPv6 addresses) in the `carbide-dns` layer. Previously, all DNS records defaulted to type `A` regardless of the address family. With this change, the record type is now derived from the IP address (IPv6 addresses produce `AAAA` records, IPv4 addresses produce `A` records). What's nice was the DNS implementation(s) were basically `AAAA`-aware throughout, sans the database views and some query defaults, e.g. - In the `dns-record` crate, `DnsResourceRecordType::AAAA` existed, with `DNS_QTYPE_AAAA = 28`. - The new PowerDNS backend stuff already correctly routes `AAAA` queries. - API handlers have already been made agnostic to record type per the prevous PRs. - Within the model, `q_type` was already a `String` and allowed for working with any type. Changes here include: - A SQL migration to switch to a family-aware `q_type`, which involved updating the existing DNS record views to return either `A` or `AAAA`, instead of just `A` like it used to. This includes query defaults/fallback -- if we can't figure it out from the `q_type` or `resource_record`, we'll always fall back to `A`. - Support for IPv6 hostname formatting -- like how we have `-` separated hostnames for IPv4 addresses, doing something similar for IPv6. Totally not as nice as IPv4, and we can always adjust this later, but it's making me miss our fun friendly names. Examples are `fd00::1` → `fd00--1.example.com` and `2001:db8::8a2e:370:7334` → `2001-db8--8a2e-370-7334.example.com`. - `AAAA` support in our `dns::legacy` integration -- we now match on `A` or `AAAA` and pass on the matching `q_type`, use `IpAddr` instead of `Ipv4Addr`, and use `RData::A` or `RData::AAAA` with the correct `RecordType`. DNS Views Updated (for reference): - `dns_records_adm_combined` - `dns_records_bmc_host_id` - `dns_records_bmc_dpu_id` - `dns_records_shortname_combined` - `dns_records_instance` It's worth noting that we do have to DROP the `dns_records` view here and re-create it. However, since this happens during the migration, the API server isn't serving yet, AND since the data is just a view, we're not losing data. It just feels weird to DROP something to me, so I wanted to call it out, even though it has no impact (and has been tested with the existing + additional tests). Updated the existing `test_dns` test to seet explicit `q_type` values to verify the IPv4 records are still correctly typed, and introduced a new `test_dns_aaaa` test which provides a full end-to-end test for `AAAA` records, where it: - Creates a managed host. - Inserts an IPv6 address (`fd00::1`) into `machine_interface_addresses` for the same interface, simulating a dual-stack environment. - Queries the "admin" view (aka `{machine_id}.adm.{domain}`) and asserts: - Both record types returned (`A` + `AAAA`). - The `AAAA` record has `content = "fd00::1"`. - The `A` record is still present with an IPv4 address - Queries the fun/friendly name view (`{hostname}.{domain}.`) and asserts the same: - `AAAA` record is present with correct content. - `A` record is also present. This exercises the new migration's `dns_records` view (which I mention above), running the new migration and verifying everything is all a-ok. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84)! Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). So, *this* PR enables end-to-end `AAAA` record support (for IPv6 addresses) in the `carbide-dns` layer. Previously, all DNS records defaulted to type `A` regardless of the address family. With this change, the record type is now derived from the IP address (IPv6 addresses produce `AAAA` records, IPv4 addresses produce `A` records). What's nice was the DNS implementation(s) were basically `AAAA`-aware throughout, sans the database views and some query defaults, e.g. - In the `dns-record` crate, `DnsResourceRecordType::AAAA` existed, with `DNS_QTYPE_AAAA = 28`. - The new PowerDNS backend stuff already correctly routes `AAAA` queries. - API handlers have already been made agnostic to record type per the prevous PRs. - Within the model, `q_type` was already a `String` and allowed for working with any type. Changes here include: - A SQL migration to switch to a family-aware `q_type`, which involved updating the existing DNS record views to return either `A` or `AAAA`, instead of just `A` like it used to. This includes query defaults/fallback -- if we can't figure it out from the `q_type` or `resource_record`, we'll always fall back to `A`. - Support for IPv6 hostname formatting -- like how we have `-` separated hostnames for IPv4 addresses, doing something similar for IPv6. Totally not as nice as IPv4, and we can always adjust this later, but it's making me miss our fun friendly names. Examples are `fd00::1` → `fd00--1.example.com` and `2001:db8::8a2e:370:7334` → `2001-db8--8a2e-370-7334.example.com`. - `AAAA` support in our `dns::legacy` integration -- we now match on `A` or `AAAA` and pass on the matching `q_type`, use `IpAddr` instead of `Ipv4Addr`, and use `RData::A` or `RData::AAAA` with the correct `RecordType`. DNS Views Updated (for reference): - `dns_records_adm_combined` - `dns_records_bmc_host_id` - `dns_records_bmc_dpu_id` - `dns_records_shortname_combined` - `dns_records_instance` It's worth noting that we do have to DROP the `dns_records` view here and re-create it. However, since this happens during the migration, the API server isn't serving yet, AND since the data is just a view, we're not losing data. It just feels weird to DROP something to me, so I wanted to call it out, even though it has no impact (and has been tested with the existing + additional tests). Updated the existing `test_dns` test to seet explicit `q_type` values to verify the IPv4 records are still correctly typed, and introduced a new `test_dns_aaaa` test which provides a full end-to-end test for `AAAA` records, where it: - Creates a managed host. - Inserts an IPv6 address (`fd00::1`) into `machine_interface_addresses` for the same interface, simulating a dual-stack environment. - Queries the "admin" view (aka `{machine_id}.adm.{domain}`) and asserts: - Both record types returned (`A` + `AAAA`). - The `AAAA` record has `content = "fd00::1"`. - The `A` record is still present with an IPv4 address - Queries the fun/friendly name view (`{hostname}.{domain}.`) and asserts the same: - `AAAA` record is present with correct content. - `A` record is also present. This exercises the new migration's `dns_records` view (which I mention above), running the new migration and verifying everything is all a-ok. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84)! Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). *This* PR updates the DHCP discovery path to be family-aware, so that DHCPv4 continues to work correctly in dual-stack environments, AND so a future DHCPv6 server can reuse [some of] the same generic code path. Rather than filtering IPv6 out of the `machine_dhcp_records` view (which would prevent reuse), there is now an added an `IpAddressFamily` parameter to the query and derive the family from the relay (`giaddr`) address; DHCPv4 relays are obviously IPv4, and DHCPv6 relays will be IPv6. This parameter gets plumbed through, starting in `discover_dhcp`, and eventually gets leveraged as part of an updated Postgres query that does a `family(address)` check and compares it to the target `IpAddressFamily`, which we derive from the relay that relayed us the DHCP message. This ensures we can correctly support dual-stack environments. I did also leave comments on some existing "DHCPv4" code where it made sense, explaining why it will never be for DHCPv6. There are a lot of differences between the two, and that's going to be worthy of a design doc pretty soon with regards to stateful vs. stateless DHCPv6, if we want to support one or the other or both, and how to implement it in a way that continues to keep dependencies on the underlying physical network down. *Note that we're still guarding around DPA (just a little more obvious now), since DPA is IPv4 only for the foreseeable future.* Existing tests continue to pass as expected, which is nice, and I added a new `test_dhcp_record_address-family` test which verifies that the updated `find_by_mac_address` query correctly filters by address family in a dual-stack scenario. The test: 1. Creates a machine via DHCPv4 discovery (gives an IPv4 relay address). 2. Inserts an IPv6 address (`fd00::42`) for the same interface to dual stack it. 3. Queries with `IpAddressFamily::Ipv4` — asserts only the IPv4 record is returned. 4. Queries with `IpAddressFamily::Ipv6` — asserts only the IPv6 record is returned. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84)! Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). *This* PR updates the DHCP discovery path to be family-aware, so that DHCPv4 continues to work correctly in dual-stack environments, AND so a future DHCPv6 server can reuse [some of] the same generic code path. Rather than filtering IPv6 out of the `machine_dhcp_records` view (which would prevent reuse), there is now an added an `IpAddressFamily` parameter to the query and derive the family from the relay (`giaddr`) address; DHCPv4 relays are obviously IPv4, and DHCPv6 relays will be IPv6. This parameter gets plumbed through, starting in `discover_dhcp`, and eventually gets leveraged as part of an updated Postgres query that does a `family(address)` check and compares it to the target `IpAddressFamily`, which we derive from the relay that relayed us the DHCP message. This ensures we can correctly support dual-stack environments. I did also leave comments on some existing "DHCPv4" code where it made sense, explaining why it will never be for DHCPv6. There are a lot of differences between the two, and that's going to be worthy of a design doc pretty soon with regards to stateful vs. stateless DHCPv6, if we want to support one or the other or both, and how to implement it in a way that continues to keep dependencies on the underlying physical network down. *Note that we're still guarding around DPA (just a little more obvious now), since DPA is IPv4 only for the foreseeable future.* Existing tests continue to pass as expected, which is nice, and I added a new `test_dhcp_record_address-family` test which verifies that the updated `find_by_mac_address` query correctly filters by address family in a dual-stack scenario. The test: 1. Creates a machine via DHCPv4 discovery (gives an IPv4 relay address). 2. Inserts an IPv6 address (`fd00::42`) for the same interface to dual stack it. 3. Queries with `IpAddressFamily::Ipv4` — asserts only the IPv4 record is returned. 4. Queries with `IpAddressFamily::Ipv6` — asserts only the IPv6 record is returned. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84)! Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). *This* PR updates the DHCP discovery path to be family-aware, so that DHCPv4 continues to work correctly in dual-stack environments, AND so a future DHCPv6 server can reuse [some of] the same generic code path. Rather than filtering IPv6 out of the `machine_dhcp_records` view (which would prevent reuse), there is now an added an `IpAddressFamily` parameter to the query and derive the family from the relay (`giaddr`) address; DHCPv4 relays are obviously IPv4, and DHCPv6 relays will be IPv6. This parameter gets plumbed through, starting in `discover_dhcp`, and eventually gets leveraged as part of an updated Postgres query that does a `family(address)` check and compares it to the target `IpAddressFamily`, which we derive from the relay that relayed us the DHCP message. This ensures we can correctly support dual-stack environments. I did also leave comments on some existing "DHCPv4" code where it made sense, explaining why it will never be for DHCPv6. There are a lot of differences between the two, and that's going to be worthy of a design doc pretty soon with regards to stateful vs. stateless DHCPv6, if we want to support one or the other or both, and how to implement it in a way that continues to keep dependencies on the underlying physical network down. *Note that we're still guarding around DPA (just a little more obvious now), since DPA is IPv4 only for the foreseeable future.* Existing tests continue to pass as expected, which is nice, and I added a new `test_dhcp_record_address-family` test which verifies that the updated `find_by_mac_address` query correctly filters by address family in a dual-stack scenario. The test: 1. Creates a machine via DHCPv4 discovery (gives an IPv4 relay address). 2. Inserts an IPv6 address (`fd00::42`) for the same interface to dual stack it. 3. Queries with `IpAddressFamily::Ipv4` — asserts only the IPv4 record is returned. 4. Queries with `IpAddressFamily::Ipv6` — asserts only the IPv6 record is returned. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
that referenced
this pull request
Feb 19, 2026
## Description Continuing to chip away at [IPv6 support](#84)! Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([#192](#192)). - Accepting IPv6 site prefixes and network segments. ([#204](#204)). - Making the IP allocator family-aware ([#217](#217)). - Making the prefix allocator family-aware ([#237](#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([#324](#324)). - Adding `AAAA` record support to DNS ([#332](#332)). *This* PR updates the DHCP discovery path to be family-aware, so that DHCPv4 continues to work correctly in dual-stack environments, AND so a future DHCPv6 server can reuse [some of] the same generic code path. Rather than filtering IPv6 out of the `machine_dhcp_records` view (which would prevent reuse), there is now an added an `IpAddressFamily` parameter to the query and derive the family from the relay (`giaddr`) address; DHCPv4 relays are obviously IPv4, and DHCPv6 relays will be IPv6. This parameter gets plumbed through, starting in `discover_dhcp`, and eventually gets leveraged as part of an updated Postgres query that does a `family(address)` check and compares it to the target `IpAddressFamily`, which we derive from the relay that relayed us the DHCP message. This ensures we can correctly support dual-stack environments. I don't expect this to be it, either. There will presumably be a fair amount of new code we'll need to add for DHCPv6 support, but I'm hoping we can keep some of the generic flows generic enough to happily handle both. I also left comments on some existing "DHCPv4" code where it made sense, explaining why it will never be for DHCPv6. There are a lot of differences between the two, and that's going to be worthy of a design doc pretty soon with regards to stateful vs. stateless DHCPv6, if we want to support one or the other or both, and how to implement it in a way that continues to keep dependencies on the underlying physical network down. *Note that we're still guarding around DPA (just a little more obvious now), since DPA is IPv4 only for the foreseeable future.* Existing tests continue to pass as expected, which is nice, and I added a new `test_dhcp_record_address-family` test which verifies that the updated `find_by_mac_address` query correctly filters by address family in a dual-stack scenario. The test: 1. Creates a machine via DHCPv4 discovery (gives an IPv4 relay address). 2. Inserts an IPv6 address (`fd00::42`) for the same interface to dual stack it. 3. Queries with `IpAddressFamily::Ipv4` — asserts only the IPv4 record is returned. 4. Queries with `IpAddressFamily::Ipv6` — asserts only the IPv6 record is returned. And again, reminder that we're not done here. Still much to do! Signed-off-by: Chet Nichols III <chetn@nvidia.com> ## Type of Change <!-- Check one that best describes this PR --> - [x] **Add** - New feature or capability - [ ] **Change** - Changes in existing functionality - [x] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [x] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Related Issues (Optional) <!-- If applicable, provide GitHub Issue. --> ## Breaking Changes - [ ] This PR contains breaking changes <!-- If checked above, describe the breaking changes and migration steps --> ## Testing <!-- How was this tested? Check all that apply --> - [x] Unit tests added/updated - [x] Integration tests added/updated - [ ] Manual testing performed - [ ] No testing required (docs, internal refactor, etc.) ## Additional Notes <!-- Any additional context, deployment notes, or reviewer guidance --> Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
As part of the [IPv6 support](NVIDIA#84), I noticed a couple of `Ipv4Addr` things that no longer need to be explicitly IPv4 due to all of the other work that has been done thus far ([NVIDIA#192](NVIDIA#192), [NVIDIA#204](NVIDIA#204), [NVIDIA#217](NVIDIA#217), [NVIDIA#237](NVIDIA#237), [NVIDIA#324](NVIDIA#324), [NVIDIA#332](NVIDIA#332), and [NVIDIA#335](NVIDIA#335). Added a simple `test_find_machine_by_ipv6` unit test to compliment the `test_find_machine` test so we have IPv4 and IPv6 coverage for `find_by_query`. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
As part of the [IPv6 support](NVIDIA#84), I noticed a couple of `Ipv4Addr` things that no longer need to be explicitly IPv4 due to all of the other work that has been done thus far ([NVIDIA#192](NVIDIA#192), [NVIDIA#204](NVIDIA#204), [NVIDIA#217](NVIDIA#217), [NVIDIA#237](NVIDIA#237), [NVIDIA#324](NVIDIA#324), [NVIDIA#332](NVIDIA#332), and [NVIDIA#335](NVIDIA#335). Added a simple `test_find_machine_by_ipv6` unit test to compliment the `test_find_machine` test so we have IPv4 and IPv6 coverage for `find_by_query`. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
that referenced
this pull request
Feb 19, 2026
## Description As part of the [IPv6 support](#84), I noticed a couple of `Ipv4Addr` things that no longer need to be explicitly IPv4 due to all of the other work that has been done thus far ([#192](#192), [#204](#204), [#217](#217), [#237](#237), [#324](#324), [#332](#332), and [#335](#335). Added a simple `test_find_machine_by_ipv6` unit test to compliment the `test_find_machine` test so we have IPv4 and IPv6 coverage for `find_by_query`. Signed-off-by: Chet Nichols III <chetn@nvidia.com> ## Type of Change <!-- Check one that best describes this PR --> - [x] **Add** - New feature or capability - [ ] **Change** - Changes in existing functionality - [ ] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [ ] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Related Issues (Optional) <!-- If applicable, provide GitHub Issue. --> ## Breaking Changes - [ ] This PR contains breaking changes <!-- If checked above, describe the breaking changes and migration steps --> ## Testing <!-- How was this tested? Check all that apply --> - [x] Unit tests added/updated - [ ] Integration tests added/updated - [ ] Manual testing performed - [ ] No testing required (docs, internal refactor, etc.) ## Additional Notes <!-- Any additional context, deployment notes, or reviewer guidance --> Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 19, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Note that while this handles allocating individual IPv6 addresses, I think there will also be a real-world application for allocating prefixes (effectively prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Note that while this handles allocating individual IPv6 addresses, I think there will also be a real-world application for allocating prefixes (effectively prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Note that while this handles allocating individual IPv6 addresses, I think there will also be a real-world application for allocating prefixes (effectively prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Note that while this handles allocating individual IPv6 addresses, I think there will also be a real-world application for allocating prefixes (effectively prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Note that while this handles allocating individual IPv6 addresses, I think there will also be a real-world application for allocating prefixes (effectively prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Note that while this handles allocating individual IPv6 addresses, I think there will also be a real-world application for allocating prefixes (effectively prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
chet
added a commit
that referenced
this pull request
Feb 20, 2026
## Description Continuing to chip away at [IPv6 support](#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([#192](#192)). - Accepting IPv6 site prefixes and network segments. ([#204](#204)). - Making the IP allocator family-aware ([#217](#217)). - Making the prefix allocator family-aware ([#237](#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([#324](#324)). - Adding `AAAA` record support to DNS ([#332](#332)). - Backend DHCP plumbing updates ([#335](#335)). *This* PR adds `ResourcePoolType::Ipv6` as a new resource pool type alongside the existing `Ipv4` and `Integer` types. IPv6 address pools can now be defined via CIDR prefix or explicit range, just like IPv4 pools today. _Note that while this handles allocating individual IPv6 addresses, there will probably also be a real-world use case for allocating prefixes (think: prefix delegation from a new `ResourcePoolType::Ipv6Prefix`), so I'm planning on doing that next as a separate PR._ No existing pools/logic are changed -- this is a new type in addition to the existing types, making the capability available for when IPv6 loopback pools, VTEP pools, or other IPv6 address pools are needed. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement. Corresponding changes include: - Adding the new `Ipv6` variant to the `ResourcePoolType` enum. - Protobuf changes to make sure the `ResourcePoolType` proto enum has a matching variant. - An equivalent `ValueType` variant. - A database migration to introduce `"ipv6"` as a new `resource_pool_type`. - Complimentary `expand_ipv6_prefix()` and `expand_ipv6_range()` functions. - Wiring in `define_by_prefix` and `define_by_range`. All existing tests still passing, and 7 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_ipv6_pool_define_allocate_release`: This tests the full lifecycle. - `test_ipv6_pool_define_by_range`: Define pool range of `fd00::1`-`fd00::11` and verify correct number of addresses. - `test_expand_ipv6_prefix_120`: Make sure a `/120` prefix expands to 255 addresses with the correct start/end IPs. - `test_expand_ipv6_prefix_rejects_large_prefix`: Make sure a `/64` is rejected because it's too large to enumerate. - `test_expand_ipv6_prefix_rejects_ipv4`: Make sure an IPv4 prefix is rejected for an IPv6 pool. - `test_expand_ipv6_range`: Make sure a range of `fd00::1`–`fd00::4` produces 3 correct addresses. - `test_expand_ipv6_range_rejects_ipv4`: Make sure an IPv4 range is rejected. Signed-off-by: Chet Nichols III <chetn@nvidia.com> ## Type of Change <!-- Check one that best describes this PR --> - [x] **Add** - New feature or capability - [ ] **Change** - Changes in existing functionality - [ ] **Fix** - Bug fixes - [ ] **Remove** - Removed features or deprecated functionality - [ ] **Internal** - Internal changes (refactoring, tests, docs, etc.) ## Related Issues (Optional) <!-- If applicable, provide GitHub Issue. --> ## Breaking Changes - [ ] This PR contains breaking changes <!-- If checked above, describe the breaking changes and migration steps --> ## Testing <!-- How was this tested? Check all that apply --> - [x] Unit tests added/updated - [x] Integration tests added/updated - [ ] Manual testing performed - [ ] No testing required (docs, internal refactor, etc.) ## Additional Notes <!-- Any additional context, deployment notes, or reviewer guidance --> Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). - Adding a new `ResourcePoolType::Ipv6Prefix` type ([NVIDIA#344](NVIDIA#344)). *This* PR is a follow-up to the `ResourcePoolType::Ipv6` introduction, adding `ResourcePoolType::Ipv6Prefix` as a new resource pool type alongside the existing `Ipv4`, `Ipv6`, and `Integer` types. Where the `Ipv6` type added support for pools of individual IPv6 addresses, this PR adds pools of entire sub-prefixes (e.g., carving/allocating multiple `/64` sub-prefixes out of a `/48`, or a range of `/120` between two `/120` prefixes. The idea is we can have a large prefix block that we can effectively allocate delegations from -- whether it's network segment prefixes, point-to-point linknets, or loopback prefix blocks. An example would be we have a `/48`, and then delegate a bunch of `/64` prefixes out of it (65k delegations). Similar to the previous change to introduce `ResourcePoolType::Ipv6`, this is a completely new type. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement, just like it was for `Ipv6`. Corresponding changes include: - The new `Ipv6Prefix` variant to `ResourcePoolType`, both in the protobuf and API model. - A matching `Ipv6Prefix` variant to `ValueType` for the `resource_pool_type` in Postgres. - An optional `delegate_prefix_len` to `ResourcePoolDef` for use when allocating sub-prefixes. - A new `expand_ipv6_prefix_delegation` function, which takes a parent prefix (e.g. `"fd00:abcd::/48"`) and a `delegation_prefix_length` (e.g. `64`), and enumerates all `/64` subprefixes from that `/48`. - A new `expand_ipv6_prefix_range` function, which takes two prefixes of matching size (e.g. `"fd00::100/120` to `"fd00:300/120"`) and enumerates all of the `/120` prefixes between them. This is to maintain the ability of "range" support for `Ipv6Prefix`, e.g. - `expand_ip_range("10.0.0.1", "10.0.0.4")` gives us 3 addresses. - `expand_ipv6_range("fd00::1", "fd00::4")` gives us 3 addresses. - `expand_ipv6_prefix_range("fd00::100/120", "fd00::300/120")` gives us 2 prefixes. - Updated `define_by_prefix(...)` so that it now also matches on `ResourcePoolType::Ipv6Prefix`. All existing tests still passing, and 10 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_expand_ipv6_prefix_delegation_48_to_64`: Tests delegation of `/64`'s out of a `/48` (65k prefixes). - `test_expand_ipv6_prefix_delegation_112_to_120`: Tests delegation of `/120`'s out of a `/112` (256 prefixes). - `test_expand_ipv6_prefix_delegation_rejects_invalid`: If the delegation prefix is less than the parent prefix, error. - `test_expand_ipv6_prefix_delegation_rejects_too_large`: Making sure we reject things that would enumerate too many prefixes. - `test_expand_ipv6_prefix_delegation_rejects_ipv4`: Yell if we get IPv4. - `test_expand_ipv6_prefix_range`: Enumerate a range of `/120` and make sure the result is correct. - `test_expand_ipv6_prefix_range_rejects_mismatched_len`: Yell if we get mismatched prefix lengths (and verify it's an `InvalidArgument`). - `test_expand_ipv6_prefix_range_rejects_unaligned`: If the prefixes aren't aligned, yell with an `InvalidArgument`. - `test_ipv6_prefix_pool_define_allocate_release`: Run through a full lifecycle: define a `/112` pool with `/120` delegations, then allocate + release. - `test_ipv6_prefix_pool_define_by_range`: Do the same, but with a range of `/120`, and verify the 16 prefixes are allocated + released. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 20, 2026
Continuing to chip away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). - Adding a new `ResourcePoolType::Ipv6Prefix` type ([NVIDIA#344](NVIDIA#344)). *This* PR is a follow-up to the `ResourcePoolType::Ipv6` introduction, adding `ResourcePoolType::Ipv6Prefix` as a new resource pool type alongside the existing `Ipv4`, `Ipv6`, and `Integer` types. Where the `Ipv6` type added support for pools of individual IPv6 addresses, this PR adds pools of entire sub-prefixes (e.g., carving/allocating multiple `/64` sub-prefixes out of a `/48`, or a range of `/120` between two `/120` prefixes. The idea is we can have a large prefix block that we can effectively allocate delegations from -- whether it's network segment prefixes, point-to-point linknets, or loopback prefix blocks. An example would be we have a `/48`, and then delegate a bunch of `/64` prefixes out of it (65k delegations). Similar to the previous change to introduce `ResourcePoolType::Ipv6`, this is a completely new type. Introduced a number of tests, including a test to verify the full lifecycle works to define, populate, allocate, and release. Since the resource pool architecture is designed around generics and string storage (`ResourcePool<T>`, `.populate()`, and `.allocate()`), this was all pretty straightfoward to implement, just like it was for `Ipv6`. Corresponding changes include: - The new `Ipv6Prefix` variant to `ResourcePoolType`, both in the protobuf and API model. - A matching `Ipv6Prefix` variant to `ValueType` for the `resource_pool_type` in Postgres. - An optional `delegate_prefix_len` to `ResourcePoolDef` for use when allocating sub-prefixes. - A new `expand_ipv6_prefix_delegation` function, which takes a parent prefix (e.g. `"fd00:abcd::/48"`) and a `delegation_prefix_length` (e.g. `64`), and enumerates all `/64` subprefixes from that `/48`. - A new `expand_ipv6_prefix_range` function, which takes two prefixes of matching size (e.g. `"fd00::100/120` to `"fd00:300/120"`) and enumerates all of the `/120` prefixes between them. This is to maintain the ability of "range" support for `Ipv6Prefix`, e.g. - `expand_ip_range("10.0.0.1", "10.0.0.4")` gives us 3 addresses. - `expand_ipv6_range("fd00::1", "fd00::4")` gives us 3 addresses. - `expand_ipv6_prefix_range("fd00::100/120", "fd00::300/120")` gives us 2 prefixes. - Updated `define_by_prefix(...)` so that it now also matches on `ResourcePoolType::Ipv6Prefix`. All existing tests still passing, and 10 new tests added to cover various angles of this, as well as a full "end to end" test to make sure we can define a pool, allocate an address, and release it. Tests are as follows: - `test_expand_ipv6_prefix_delegation_48_to_64`: Tests delegation of `/64`'s out of a `/48` (65k prefixes). - `test_expand_ipv6_prefix_delegation_112_to_120`: Tests delegation of `/120`'s out of a `/112` (256 prefixes). - `test_expand_ipv6_prefix_delegation_rejects_invalid`: If the delegation prefix is less than the parent prefix, error. - `test_expand_ipv6_prefix_delegation_rejects_too_large`: Making sure we reject things that would enumerate too many prefixes. - `test_expand_ipv6_prefix_delegation_rejects_ipv4`: Yell if we get IPv4. - `test_expand_ipv6_prefix_range`: Enumerate a range of `/120` and make sure the result is correct. - `test_expand_ipv6_prefix_range_rejects_mismatched_len`: Yell if we get mismatched prefix lengths (and verify it's an `InvalidArgument`). - `test_expand_ipv6_prefix_range_rejects_unaligned`: If the prefixes aren't aligned, yell with an `InvalidArgument`. - `test_ipv6_prefix_pool_define_allocate_release`: Run through a full lifecycle: define a `/112` pool with `/120` delegations, then allocate + release. - `test_ipv6_prefix_pool_define_by_range`: Do the same, but with a range of `/120`, and verify the 16 prefixes are allocated + released. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 22, 2026
Still chipping away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). - Adding a new `ResourcePoolType::Ipv6` type ([NVIDIA#344](NVIDIA#344)). - Adding a new `ResourcePoolType::Ipv6Prefix` type ([NVIDIA#345](NVIDIA#345)). All of that work has been on the "core" side -- the API, database, allocator, DNS, resource pools, etc. *This* PR is the first in a new series of changes focused on the agent side. The goal is, of course, to have IPv6 support plumbed through the agent, so it can make its way to HBN (via `nvue`) for confguring addresses, routes, ACLs, BGP, etc. Similar to "core" efforts, I'm taking a simple starting point by adjusting the `loopback_ip` fields from `Ipv4Addr` to `IpAddr` across the agent's config structs (and corresponding CLI argument types). Similar to "core" changes like this being a noop, this is no different, and the test-verified rendered template output remains the same. Changes here include: - `InterfacesConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. This only gets used as `conf.loopback_ip.to_string()` to feed templates. - `FrrConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. Same thing as above -- only used as `conf.loopback_ip.to_string()` to feed templates. - `loopback_ip` going from `Ipv4Addr` to `IpAddr` in `NvueOptions`, `FrrOptions`, and `InterfacesOptions`. Since these are all parsed as `IpAddr::from_str`, they continued to work as-is. - Dropping some comments, mostly about IPv4 things that will always be IPv4 (mainly around DHCPv4). The existing tests (including `test_write_frr`) continues to pass, rendering templates as expected. IPv6 templates are NOT being introduced here yet -- for now, the important bit is widening types to `IpAddr` and making sure it continues to work as a drop-in with IPv6. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 22, 2026
Still chipping away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). - Adding a new `ResourcePoolType::Ipv6` type ([NVIDIA#344](NVIDIA#344)). - Adding a new `ResourcePoolType::Ipv6Prefix` type ([NVIDIA#345](NVIDIA#345)). All of that work has been on the "core" side -- the API, database, allocator, DNS, resource pools, etc. *This* PR is the first in a new series of changes focused on the agent side. The goal is, of course, to have IPv6 support plumbed through the agent, so it can make its way to HBN (via `nvue`) for confguring addresses, routes, ACLs, BGP, etc. Similar to "core" efforts, I'm taking a simple starting point by adjusting the `loopback_ip` fields from `Ipv4Addr` to `IpAddr` across the agent's config structs (and corresponding CLI argument types). Similar to "core" changes like this being a noop, this is no different, and the test-verified rendered template output remains the same. Changes here include: - `InterfacesConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. This only gets used as `conf.loopback_ip.to_string()` to feed templates. - `FrrConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. Same thing as above -- only used as `conf.loopback_ip.to_string()` to feed templates. - `loopback_ip` going from `Ipv4Addr` to `IpAddr` in `NvueOptions`, `FrrOptions`, and `InterfacesOptions`. Since these are all parsed as `IpAddr::from_str`, they continued to work as-is. - Dropping some comments, mostly about IPv4 things that will always be IPv4 (mainly around DHCPv4). The existing tests (including `test_write_frr`) continues to pass, rendering templates as expected. IPv6 templates are NOT being introduced here yet -- for now, the important bit is widening types to `IpAddr` and making sure it continues to work as a drop-in with IPv6. Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 22, 2026
Still chipping away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). - Adding a new `ResourcePoolType::Ipv6` type ([NVIDIA#344](NVIDIA#344)). - Adding a new `ResourcePoolType::Ipv6Prefix` type ([NVIDIA#345](NVIDIA#345)). All of that work has been on the "core" side -- the API, database, allocator, DNS, resource pools, etc. *This* PR is the first in a new series of changes focused on the agent side. The goal is, of course, to have IPv6 support plumbed through the agent, so it can make its way to HBN (via `nvue`) for configuring addresses, routes, ACLs, BGP, etc. Similar to "core" efforts, I'm taking a simple starting point by widening from `Ipv4Addr` to `IpAddr` across some of the more low-hanging agent config structs, CLI argument types, and service address types. Just like previous changes being a noop, this is no different, and the test-verified rendered template output remains the same. Changes included: - `InterfacesConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. This only gets used as `conf.loopback_ip.to_string()` to feed templates. - `FrrConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. Same thing as above -- only used as `conf.loopback_ip.to_string()` to feed templates. - `loopback_ip` going from `Ipv4Addr` to `IpAddr` in `NvueOptions`, `FrrOptions`, and `InterfacesOptions`. Since these are all parsed via `IpAddr::from_str`, they continued to work as-is. - `ServiceAddresses.pxe_ip` going from `Ipv4Addr` to `IpAddr`. Despite the field name, this is the UEFI HTTP boot server address, which would carry over to DHCPv6 just fine. - `ServiceAddresses.ntpservers` going from `Vec<Ipv4Addr>` to `Vec<IpAddr>`. NTP servers are still a DHCPv6 "feature". - At the `dhcp::build_server_config()` call site, added IPv4 filtering for `pxe_ip`, `ntpservers`, and `nameservers` (which was already filtered) before passing to the DHCPv4 config builder. `ServiceAddresses` now holds both families, but DHCPv4 options can only carry IPv4 addresses. - Left comments on things that are intentionally staying IPv4 for now -- the `DhcpOptions` CLI struct (DHCPv4-specific), and the internal HBN bridge prefix parsing (`169.254.x.x` link-local plumbing, though an IPv6 equivalent may be needed in the future). The existing tests (including `test_write_frr`) continue to pass, rendering templates as expected. IPv6 templates are NOT being introduced here yet -- for now, the important bit is widening types to `IpAddr` and making sure it continues to work as a drop-in with IPv4 Signed-off-by: Chet Nichols III <chetn@nvidia.com>
chet
added a commit
to chet/bare-metal-manager-core
that referenced
this pull request
Feb 22, 2026
Still chipping away at [IPv6 support](NVIDIA#84). Work thus far has included: - Moving to `IpNetwork` and `IpAddress` throughout ([NVIDIA#192](NVIDIA#192)). - Accepting IPv6 site prefixes and network segments. ([NVIDIA#204](NVIDIA#204)). - Making the IP allocator family-aware ([NVIDIA#217](NVIDIA#217)). - Making the prefix allocator family-aware ([NVIDIA#237](NVIDIA#237)). - Removing some more API guards and enhancing the `IdentifyAddressFamily` trait ([NVIDIA#324](NVIDIA#324)). - Adding `AAAA` record support to DNS ([NVIDIA#332](NVIDIA#332)). - Backend DHCP plumbing updates ([NVIDIA#335](NVIDIA#335)). - Adding a new `ResourcePoolType::Ipv6` type ([NVIDIA#344](NVIDIA#344)). - Adding a new `ResourcePoolType::Ipv6Prefix` type ([NVIDIA#345](NVIDIA#345)). All of that work has been on the "core" side -- the API, database, allocator, DNS, resource pools, etc. *This* PR is the first in a new series of changes focused on the agent side. The goal is, of course, to have IPv6 support plumbed through the agent, so it can make its way to HBN (via `nvue`) for configuring addresses, routes, ACLs, BGP, etc. Similar to "core" efforts, I'm taking a simple starting point by widening from `Ipv4Addr` to `IpAddr` across some of the more low-hanging agent config structs, CLI argument types, and service address types. Just like previous changes being a noop, this is no different, and the test-verified rendered template output remains the same. Changes included: - `InterfacesConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. This only gets used as `conf.loopback_ip.to_string()` to feed templates. - `FrrConfig.loopback_ip` going from `Ipv4Addr` to `IpAddr`. Same thing as above -- only used as `conf.loopback_ip.to_string()` to feed templates. - `loopback_ip` going from `Ipv4Addr` to `IpAddr` in `NvueOptions`, `FrrOptions`, and `InterfacesOptions`. Since these are all parsed via `IpAddr::from_str`, they continued to work as-is. - `ServiceAddresses.pxe_ip` going from `Ipv4Addr` to `IpAddr`. Despite the field name, this is the UEFI HTTP boot server address, which would carry over to DHCPv6 just fine. - `ServiceAddresses.ntpservers` going from `Vec<Ipv4Addr>` to `Vec<IpAddr>`. NTP servers are still a DHCPv6 "feature". - At the `dhcp::build_server_config()` call site, added IPv4 filtering for `pxe_ip`, `ntpservers`, and `nameservers` (which was already filtered) before passing to the DHCPv4 config builder. `ServiceAddresses` now holds both families, but DHCPv4 options can only carry IPv4 addresses. - Left comments on things that are intentionally staying IPv4 for now -- the `DhcpOptions` CLI struct (DHCPv4-specific), and the internal HBN bridge prefix parsing (`169.254.x.x` link-local plumbing, though an IPv6 equivalent may be needed in the future). The existing tests (including `test_write_frr`) continue to pass, rendering templates as expected. IPv6 templates are NOT being introduced here yet -- for now, the important bit is widening types to `IpAddr` and making sure it continues to work as a drop-in with IPv4 Signed-off-by: Chet Nichols III <chetn@nvidia.com>
10 tasks
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.
Description
Continuing the IPv6 support work. This is the third PR.
Work thus far has included:
IpNetworkandIpAddressthroughout (#192).And today: adding IPv6 support to IP address allocation.
Similar to the previous PRs, this does NOT enable IPv6 support (i.e. there won't be any
DHCPv6traffic coming in yet), but this DOES contribute to the foundational work of supporting IPv6. Eventually, we'll be able to start actually accepting requests and config for using IPv6, but there's a lot of backend work that needs to be done to get there. Trying to take it a layer at a time, and pieces of each layer at that. This is PR #3 of what is going to be many.In any case, as mentioned, this PR is focused on adding IPv6 support to address allocation, specifically the
IpAllocator, which is being made IPv6-capable by removing all IPv4-only guards, [re]introducingAddressSelectionStrategyto cleanly drive allocation behavior, and unblocking IPv6 allocation across all code paths, including:The goal is to prepare the allocation layer so that when DHCPv6 is added later, everything beneath it already works -- existing deployments and config are unaffected, as existing config is all parsed as IPv4 and uses [the same] IPv4 code paths and allocation strategies (which are verified with both existing AND new tests).
One of the particularly exciting highlights here is starting to use the
AddressSelectionStrategyfor something. Previously, we just passed aroundAddressSelectionStrategy::Automaticfor everything. Now, we actually use it for address selection, by saying how we want to select the next IP.::NextAvailableIpis synonymous with::Automatic-- we pick the next/32or/128depending on the address family.::NextAvailablePrefix(uint)gives us support for allocating a prefix that is wider than/32or/128.This allowed us to remove the
prefix_lengthfrom theIpAllocatorconstructor. I was never fully happy with it being there. It seemed to make sense at the time, but it also seemed like there was something better we could do. Making it a part ofAddressSelectionStrategyis actually what should have happened to begin with.It's also worth noting the SQL
next_machine_interface_v4_ipfast-path got removed here. It was a nice idea to have, but it didn't play well with dual-stacking interfaces (it actually got rid of dual stack support entirely when it was introduced), and it was only ever going to support IPv4. If we have performance concerns about quickly allocating many machines, we can definitely revisit it, but unfortunately it won't work as-is for now. The previous logic has been put back, with some enhancements for dual stacking.Some callouts around backwards compatibility (in addition to tests):
DHCP is still IPv4-only
carbide-dhcpspeaks DHCPv4 exclusively — it parsesIpv4Addr::from_str(&forge_response.address)on the response and callsset_yiaddr(allocated_address). Even if a tenant segment is configured to support IPv6 prefixes, the DHCP server will never request an IPv6 lease. The allocator is ready, but the trigger isn't there yet.Machine interface (underlay) IPv4 AND IPv6 work end-to-end
If an operator configures an underlay/admin segment with IPv6 prefixes,
machine_interface::create()will allocate IPv6 addresses via theIpAllocator. The hostname generation, DB writes, and uniqueness constraints all work correctly, in addition to IPv4 continuing to work (using the SQL-based IPv4 allocator when relevant).Existing IPv4 behavior is untouched
Again,
NextAvailableIpresolves to/32for IPv4 — identical to the old hardcodedprefix_length: 32. All existing IPv4 unit and integration tests continue to pass unmodified.Tests added:
test_ip_allocation_ipv6test_ipv6_allocation_single_address::4.test_ipv6_num_free_cappednum_free()caps atu32::MAXfor large IPv6 prefixes (/64).test_ipv6_build_allocated_networkstest_address_to_hostname_v4test_address_to_hostname_v6test_address_to_hostname_v6_loopback::1correctly expands to0000-0000-...-0001.test_next_machine_interface_v4_iptest_machine_interface_create_with_ipv6_prefixTests updated:
test_ip_allocation_ipv4_and_6test_get_network_sizeSigned-off-by: Chet Nichols III chetn@nvidia.com
Type of Change
Related Issues (Optional)
#84
Breaking Changes
Testing
Additional Notes