Skip to content

Conversation

@zeeshanlakhani
Copy link
Collaborator

@zeeshanlakhani zeeshanlakhani commented Dec 1, 2025

Previously, each silo could only have one default IP pool. This change allows one default pool per (pool_type, ip_version) combination, enabling silos to have separate defaults for:

  • Unicast IPv4
  • Unicast IPv6
  • Multicast IPv4
  • Multicast IPv6

Now, each default can be set or unset and demoted independently. Unsetting the unicast IPv4 default does not affect the multicast IPv4 default, for example.

Key changes:

  • Add pool_type and ip_version columns to ip_pool_resource (denormalized from parent ip_pool for unique index)
  • Replace unique index with partial index on (resource_id, pool_type, ip_version) WHERE is_default = true
  • Rename IpPoolResourceLink to IncompleteIpPoolResource to reflect that pool_type/ip_version are populated by the linking query

Updates 12/11/2025:

We add an ip_version field that allows callers to specify V4 or V6 preference when
allocating from default IP pools. This is required when multiple default pools of different IP versions exist. Without it, the system cannot determine which pool to use, and calls fail.

This involves an API version change. Old API versions predate ip_version support and only had V4 pools, so conversions from old types default to V4 to maintain backward compatibility. ip_version is only necessary when using default pools.

Ephemeral and floating IPs always allocate from unicast pools, so they don't need pool_type — only ip_version for V4/V6 disambiguation. Multicast groups handle pool type selection separately (ASM vs SSM) with members.

Now, the API versions are broken up into:

  • v2025112000: Disk types (Crucible -> Distributed rename)
  • v2025120300: Multicast types (before implicit lifecycle, pub for
    http_entrypoints.rs access)
  • v2025120500: FloatingIpCreate/EphemeralIpCreate without ip_version

Previously, each silo could only have one default IP pool. This change
allows one default pool per (pool_type, ip_version) combination, enabling
silos to have separate defaults for:
  - Unicast IPv4
  - Unicast IPv6
  - Multicast IPv4
  - Multicast IPv6

Now, each default can be set or unset and demoted independently.
Unsetting the unicast IPv4 default does not affect the multicast IPv4
default, for example.

Key changes:
  - Add `pool_type` and `ip_version` columns to `ip_pool_resource`
    (denormalized from parent `ip_pool` for unique index)
  - Replace unique index with partial index on (resource_id, pool_type,
    ip_version) WHERE is_default = true
  - Rename `IpPoolResourceLink` to `IncompleteIpPoolResource` to reflect
    that pool_type/ip_version are populated by the linking query
@zeeshanlakhani zeeshanlakhani self-assigned this Dec 10, 2025
The `ip_version` field allows callers to specify V4 or V6 preference when
allocating from default IP pools. This is required when multiple default
pools of different IP versions exist. Without it, the system cannot
determine which pool to use, and calls fail.

This involves an API version change. Old API versions predate
`ip_version` support and only had V4 pools, so conversions from old
types default to V4 to maintain backward compatibility. `ip_version` is
only necessary when using default pools.

Ephemeral and floating IPs always allocate from unicast pools, so they
don't need `pool_type` — only `ip_version` for V4/V6 disambiguation.
Multicast groups handle pool type selection separately (ASM vs SSM)
with members.

Now, the API versions are broken up into:
  - v2025112000: Disk types (Crucible -> Distributed rename)
  - v2025120300: Multicast types (before implicit lifecycle, pub for
    http_entrypoints.rs access)
  - v2025120500: FloatingIpCreate/EphemeralIpCreate without `ip_version`
Copy link
Collaborator

@bnaecker bnaecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not able to comment on a lot of the multicast-specific stuff, but the API changes around IP versions and default pools looks good to me. Just have a few small suggestions!

// If `ip_version` was not specified and we have multiple pools of
// different IP versions, return an error asking the caller to specify
// which version.
if ip_version.is_none() && pools.len() > 1 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth factoring this out to a function, since it's used several places. Not critical though.

// different IP versions, return an error asking the caller to specify
// which version.
if ip_version.is_none() && pools.len() > 1 {
let has_v4 = pools.iter().any(|p| p.ip_version == IpVersion::V4);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be simpler to iterate once, extract the version, and pull into a set. Then check if the set's length is > 1. Something like:

if pools.iter().map(|ip| ip.ip_version).collect::<HashSet<_>>().len() > 1 {
    return Err(...);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants