Skip to content

Conversation

@jgallagher
Copy link
Contributor

This PR is large-ish but very boilerplatey. This is a prerequisite for the planner work to avoid reading expunged zones @smklein pointed out in #9521 (comment).

We add a last_allocated_ip_subnet_offset field to BlueprintSledConfig, along with a last_allocated_ip() method that adds the offset to the sled's subnet. The rest is fallout of using that field:

  1. Many expectorate changes to add a new "last allocated IP" line
  2. New blippy check that no sled has a zone with an IP above the last allocated IP
  3. The planner now uses this field when creating each sled's underlay IP allocator instead of scraping "all in-service and expunged zones" to find all the ever-used-on-this-sled IPs

Staged on top of #9549.

@@ -0,0 +1,59 @@
-- Working with INET values in SQL is "fun".
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This migration query is quite horrifying IMO. I would love suggestions to make it less so.

// to assume that addresses in this subnet are available.
pub const SLED_RESERVED_ADDRESSES: u16 = 32;

static_assertions::const_assert_eq!(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Document this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this because I was concerned some places for the new field semantically wanted to use RSS_RESERVED_ADDRESSES and others were using SLED_RESERVED_ADDRESSES, and those mixed uses only worked if they both had the same value. With the switch to the newtype, I don't think that's true anymore (because it enforces a minimum, and if RSS_RESERVED_ADDRESSES went higher that would be fine), so I just took this back out.

BlueprintSledConfig {
state: SledState::Active,
subnet: Ipv6Subnet::new(Ipv6Addr::LOCALHOST),
last_allocated_ip_subnet_offset: RSS_RESERVED_ADDRESSES,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since this is used in a lot of tests and the connection feels pretty non-obvious, I wonder if we could document this better somehow? Maybe another constant (TESTING_INITIAL_LAST_ALLOCATED_IP_SUBNET_OFFSET is maybe long...) with a comment about it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I really don't love another constant; we already have both RSS_RESERVED_ADDRESSES and SLED_RESERVED_ADDRESSES that both mean "the starting point of what Reconfigurator can use". I think we only have two because SLED_RESERVED_ADDRESSES is supposed to be for special IPs like "gz" and "switch zone", except RSS stomps all over it when assigning zone IPs.

I did briefly consider making this a newtype instead of a raw u16; then these could all be something like LastAllocatedIpOffset::initial(). Would that be better?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think it's too bad to have a third constant, in that they're all right near each other, documented together, and have static asserts. In fact, I wouldn't define this one to be 32 -- I'd define it as the value of that other constant explicitly. More like an alias.

A different type with a named constructor would also work. You don't need a separate type to make it a free function... but then it may as well be a constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went with a newtype in 27a7e0d - what do you think?

subnet INET NOT NULL,

-- the last allocated IP within `subnet` used by the blueprint
last_allocated_ip_subnet_offset INT4 NOT NULL,
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think about a constraint between 0 and 65K?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added in 61502ee

Comment on lines 42 to 47
-- Final arg to `substr()`: this trims off the leading
-- `::` in the `::NNNN` we produced above.
3),
-- Final args to `lpad()`: this ensure we always have
-- exactly 4 hex digits, left padding with 0 if needed.
4, '0')
Copy link
Collaborator

Choose a reason for hiding this comment

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

These seem aligned weirdly for the functions that they're arguments to?

Comment on lines 35 to 52
SELECT ('x' ||
lpad(
substr(
-- bitwise & the IP with a /112 hostmask, which
-- squishes this IP down to the string '::NNNN',
-- where there will be 1-4 hex-valued X characters.
host(primary_service_ip & hostmask('::/112')),
-- Final arg to `substr()`: this trims off the leading
-- `::` in the `::NNNN` we produced above.
3),
-- Final args to `lpad()`: this ensure we always have
-- exactly 4 hex digits, left padding with 0 if needed.
4, '0')
-- We concatenated a literal 'x' prefix onto the front of the
-- `NNNN` value we just produced, which causes `bit(16)` to
-- interpret it as a 16-bit hex value (which it is!). Then
-- convert that bitstring into an integer.
)::bit(16)::int AS final_hextet
Copy link
Collaborator

Choose a reason for hiding this comment

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

ChatGPT tells me and I've casually confirmed that you can treat inet values as integers. So this works in dogfood to compute the offset for a given row:

root@[fd00:1122:3344:10b::3]:32221/omicron> select sled_id,primary_service_ip,((primary_service_ip & hostmask('::/112')) - '::'::inet) as offset from bp_omicron_zone where blueprint_id = '01155c9f-f124-41b1-aafd-0bc132d22598';
                sled_id                |   primary_service_ip   | offset
---------------------------------------+------------------------+---------
  b886b58a-1e3f-4be1-b9f2-0c2e66c6bc88 | fd00:1122:3344:106::c  |     12
  0c7011f7-a4bf-4daf-90cc-1c2410103300 | fd00:1122:3344:2::1    |      1
  f15774c1-b8e5-434f-a493-ec43f96cba06 | fd00:1122:3344:105::28 |     40
...
  7b862eb6-7f50-4c2f-b9a6-0d12ac913d3c | fd00:1122:3344:101::45 |     69
  f15774c1-b8e5-434f-a493-ec43f96cba06 | fd00:1122:3344:105::22 |     34
  b886b58a-1e3f-4be1-b9f2-0c2e66c6bc88 | fd00:1122:3344:106::d  |     13
(698 rows)

Assuming I did the right thing, maybe that could clean a bunch of this up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

... yeah that's way better. Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed in 8d55a7d

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