Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,8 @@ ntp-admin-client = { path = "clients/ntp-admin-client" }
ntp-admin-v1-client = { path = "clients/ntp-admin-v1-client" }
ntp-admin-types = { path = "ntp-admin/types" }
ntp-admin-types-versions = { path = "ntp-admin/types/versions" }
mg-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "7696ee48d5ee29a917dea459e281fe2e8ff20513" }
ddm-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "7696ee48d5ee29a917dea459e281fe2e8ff20513" }
mg-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "65ecbf283d8f7b9d5326ec5996d7e9d2df2dd453" }
ddm-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "65ecbf283d8f7b9d5326ec5996d7e9d2df2dd453" }
multimap = "0.10.1"
nexus-auth = { path = "nexus/auth" }
nexus-background-task-interface = { path = "nexus/background-task-interface" }
Expand Down Expand Up @@ -674,7 +674,7 @@ omicron-workspace-hack = "0.1.0"
omicron-zone-package = "0.12.2"
oxide-client = { path = "clients/oxide-client" }
oxide-tokio-rt = "0.1.4"
oxide-vpc = { git = "https://github.com/oxidecomputer/opte", rev = "2c6efefe14321dafe7e9e80129d38316adb2d238", features = [ "api", "std" ] }
oxide-vpc = { git = "https://github.com/oxidecomputer/opte", rev = "84e91b62621406f38e4d0870a92bafacad96536e", features = [ "api", "std" ] }
oxlog = { path = "dev-tools/oxlog" }
oxnet = "0.1.4"
once_cell = "1.21.3"
Expand All @@ -683,7 +683,7 @@ openapiv3 = "2.2.0"
# must match samael's crate!
openssl = "0.10"
openssl-sys = "0.9"
opte-ioctl = { git = "https://github.com/oxidecomputer/opte", rev = "2c6efefe14321dafe7e9e80129d38316adb2d238" }
opte-ioctl = { git = "https://github.com/oxidecomputer/opte", rev = "84e91b62621406f38e4d0870a92bafacad96536e" }
oso = "0.27"
owo-colors = "4.2.2"
oximeter = { path = "oximeter/oximeter" }
Expand Down Expand Up @@ -749,7 +749,7 @@ rats-corim = { git = "https://github.com/oxidecomputer/rats-corim.git", rev = "f
raw-cpuid = { git = "https://github.com/oxidecomputer/rust-cpuid.git", rev = "a4cf01df76f35430ff5d39dc2fe470bcb953503b" }
rayon = "1.10"
rcgen = "0.12.1"
rdb-types = { git = "https://github.com/oxidecomputer/maghemite", rev = "7696ee48d5ee29a917dea459e281fe2e8ff20513" }
rdb-types = { git = "https://github.com/oxidecomputer/maghemite", rev = "65ecbf283d8f7b9d5326ec5996d7e9d2df2dd453" }
reconfigurator-cli = { path = "dev-tools/reconfigurator-cli" }
reedline = "0.40.0"
ref-cast = "1.0"
Expand Down
10 changes: 10 additions & 0 deletions common/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ pub const AZ_PREFIX: u8 = 48;
pub const RACK_PREFIX: u8 = 56;
pub const SLED_PREFIX: u8 = 64;

/// Default Ethernet MTU for external-facing OPTE ports, in bytes. Used when
/// the per-instance jumbo-frames opt-in is unset or when the fleet-wide
/// opt-in is disabled (RFD 689).
pub const EXTERNAL_DEFAULT_MTU: u32 = 1500;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We're not actually reading this anywhere. Should we be sending this down rather than None? Obviously OPTE will pick the same value, but I being explicit about this as a choice the control plane is making seems beneficial to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed


/// Effective MTU for external-facing OPTE ports when jumbo frames have been
/// opted into (RFD 689 §Implementation). 500 bytes of headroom under the
/// 9000 byte underlay MTU leaves room for VPC encapsulation overhead.
pub const EXTERNAL_JUMBO_FRAMES_MTU: u32 = 8500;

// Multicast constants

/// IPv4 Source-Specific Multicast (SSM) subnet.
Expand Down
1 change: 1 addition & 0 deletions end-to-end-tests/src/instance_launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ async fn instance_launch() -> Result<()> {
anti_affinity_groups: Vec::new(),
cpu_platform: None,
multicast_groups: Vec::new(),
enable_jumbo_frames: false,
})
.send()
.await?;
Expand Down
2 changes: 1 addition & 1 deletion illumos-utils/src/opte/non_illumos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl Handle {
&self,
name: &str,
cfg: VpcCfg,
_: bool,
_mtu: Option<u32>,
) -> Result<NoResp, OpteError> {
let name = name.to_string();
let IpCfg::Ipv4(ip_cfg) = cfg.ip_cfg else {
Expand Down
13 changes: 12 additions & 1 deletion illumos-utils/src/opte/port_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ pub struct PortCreateParams<'a> {
pub firewall_rules: &'a [ResolvedVpcFirewallRule],
pub dhcp_config: DhcpCfg,
pub attached_subnets: Vec<AttachedSubnet>,
/// MTU to set on the xde device, in bytes. If `None`, OPTE applies its
/// default (1500). Used by RFD 689 jumbo-frame opt-in.
pub mtu: Option<u32>,
}

impl<'a> TryFrom<&PortCreateParams<'a>> for IpCfg {
Expand Down Expand Up @@ -371,6 +374,7 @@ impl PortManager {
firewall_rules,
dhcp_config,
attached_subnets: _,
mtu,
} = params;
let is_service =
matches!(nic.kind, NetworkInterfaceKind::Service { .. });
Expand Down Expand Up @@ -410,7 +414,7 @@ impl PortManager {
);
let hdl = {
let hdl = Handle::new()?;
hdl.create_xde(&port_name, vpc_cfg, /* passthru = */ false)?;
hdl.create_xde(&port_name, vpc_cfg, mtu)?;
hdl
};
let (port, ticket) = {
Expand Down Expand Up @@ -1335,6 +1339,7 @@ mod tests {
dns6_servers: Vec::new(),
},
attached_subnets: vec![],
mtu: None,
})
.unwrap();

Expand Down Expand Up @@ -1514,6 +1519,7 @@ mod tests {
dns6_servers: Vec::new(),
},
attached_subnets: vec![],
mtu: None,
})
.unwrap();

Expand Down Expand Up @@ -1685,6 +1691,7 @@ mod tests {
dns6_servers: vec![],
},
attached_subnets: vec![],
mtu: None,
};
let IpCfg::Ipv4(oxide_vpc::api::Ipv4Cfg {
vpc_subnet,
Expand Down Expand Up @@ -1758,6 +1765,7 @@ mod tests {
dns6_servers: vec![],
},
attached_subnets: vec![],
mtu: None,
};
let IpCfg::Ipv6(oxide_vpc::api::Ipv6Cfg {
vpc_subnet,
Expand Down Expand Up @@ -1842,6 +1850,7 @@ mod tests {
dns6_servers: vec![],
},
attached_subnets: vec![],
mtu: None,
};
let IpCfg::DualStack { ipv4, ipv6 } = IpCfg::try_from(&prs).unwrap()
else {
Expand Down Expand Up @@ -1932,6 +1941,7 @@ mod tests {
dns6_servers: vec![],
},
attached_subnets: vec![],
mtu: None,
};
let _ = IpCfg::try_from(&prs).expect_err(
"Should fail to convert with public IPv6 and private IPv4",
Expand Down Expand Up @@ -1978,6 +1988,7 @@ mod tests {
dns6_servers: vec![],
},
attached_subnets: vec![],
mtu: None,
};
let _ = IpCfg::try_from(&prs).expect_err(
"Should fail to convert with public IPv4 and private IPv6",
Expand Down
9 changes: 9 additions & 0 deletions nexus/db-model/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ pub struct Instance {
/// a sled by any other constraints the instance will be incarnated with the
/// most general CPU platform supported by the selected sled.
pub cpu_platform: Option<InstanceCpuPlatform>,

/// Per RFD 689: when true, the instance has opted in to jumbo frames
/// (8500 byte MTU) on its primary OPTE interface. The effective MTU
/// also depends on the fleet-wide setting in
/// `system_networking_settings`; if that flag is off the OPTE port is
/// created with the default MTU regardless of this column. Changes to
/// this column only take effect on the next instance restart.
pub enable_jumbo_frames: bool,
}

impl Instance {
Expand Down Expand Up @@ -185,6 +193,7 @@ impl Instance {
boot_disk_id: None,
intended_state,
cpu_platform: params.cpu_platform.map(Into::into),
enable_jumbo_frames: params.enable_jumbo_frames,
}
}

Expand Down
2 changes: 2 additions & 0 deletions nexus/db-model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ mod serde_time_delta;
mod silo_auth_settings;
mod switch_interface;
mod switch_port;
mod system_networking_settings;
mod target_release;
mod trust_quorum;
mod v2p_mapping;
Expand Down Expand Up @@ -373,6 +374,7 @@ pub use support_bundle::*;
pub use switch::*;
pub use switch_interface::*;
pub use switch_port::*;
pub use system_networking_settings::*;
pub use target_release::*;
pub use trust_quorum::*;
pub use tuf_repo::*;
Expand Down
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock};
///
/// This must be updated when you change the database schema. Refer to
/// schema/crdb/README.adoc in the root of this repository for details.
pub const SCHEMA_VERSION: Version = Version::new(261, 0, 0);
pub const SCHEMA_VERSION: Version = Version::new(262, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -28,6 +28,7 @@ pub static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = LazyLock::new(|| {
// | leaving the first copy as an example for the next person.
// v
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
KnownVersion::new(262, "external-jumbo-frames"),
KnownVersion::new(261, "remove-add-zones-with-mupdate-override"),
KnownVersion::new(260, "ereport-trim-serial-trailing-nulls"),
KnownVersion::new(259, "vmm-failure-reason"),
Expand Down
37 changes: 37 additions & 0 deletions nexus/db-model/src/system_networking_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use chrono::{DateTime, Utc};
use nexus_db_schema::schema::system_networking_settings;
use serde::{Deserialize, Serialize};

/// Singleton row holding fleet-wide networking settings (RFD 689).
#[derive(
Queryable,
Insertable,
Debug,
Clone,
Selectable,
Serialize,
Deserialize,
AsChangeset,
)]
#[diesel(table_name = system_networking_settings)]
pub struct SystemNetworkingSettings {
pub singleton: bool,
pub time_created: DateTime<Utc>,
pub time_modified: DateTime<Utc>,
/// When true, end users may opt in to jumbo frames on the primary
/// interface of an instance. When false, the per-instance opt-in is
/// ignored and OPTE ports are created with the default MTU.
pub external_jumbo_frames_opt_in_enabled: bool,
}

/// Updates to the [`SystemNetworkingSettings`] singleton.
#[derive(AsChangeset)]
#[diesel(table_name = system_networking_settings)]
pub struct SystemNetworkingSettingsUpdate {
pub external_jumbo_frames_opt_in_enabled: Option<bool>,
pub time_modified: DateTime<Utc>,
}
21 changes: 21 additions & 0 deletions nexus/db-queries/src/db/datastore/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,26 @@ impl DataStore {
Ok(instance_and_vmm)
}

/// Update the per-instance jumbo-frames opt-in (RFD 689). Changes take
/// effect on the next instance restart.
pub async fn instance_set_enable_jumbo_frames(
&self,
opctx: &OpContext,
authz_instance: &authz::Instance,
enable_jumbo_frames: bool,
) -> Result<(), Error> {
opctx.authorize(authz::Action::Modify, authz_instance).await?;
use nexus_db_schema::schema::instance::dsl as instance_dsl;
diesel::update(instance_dsl::instance)
.filter(instance_dsl::id.eq(authz_instance.id()))
.filter(instance_dsl::time_deleted.is_null())
.set(instance_dsl::enable_jumbo_frames.eq(enable_jumbo_frames))
.execute_async(&*self.pool_connection_authorized(opctx).await?)
.await
.map_err(|e| public_error_from_diesel(e, ErrorHandler::Server))?;
Ok(())
}

/// Set the boot disk on an instance, bypassing the rest of an instance
/// update. You probably don't need this; it's only used at the end of
/// instance creation, since the boot disk can't be set until the new
Expand Down Expand Up @@ -2376,6 +2396,7 @@ mod tests {
auto_restart_policy: Default::default(),
anti_affinity_groups: Vec::new(),
multicast_groups: Vec::new(),
enable_jumbo_frames: false,
},
),
)
Expand Down
1 change: 1 addition & 0 deletions nexus/db-queries/src/db/datastore/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ mod tests {
auto_restart_policy: Default::default(),
anti_affinity_groups: Vec::new(),
multicast_groups: Vec::new(),
enable_jumbo_frames: false,
},
),
)
Expand Down
1 change: 1 addition & 0 deletions nexus/db-queries/src/db/datastore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ mod support_bundle;
mod switch;
mod switch_interface;
mod switch_port;
mod system_networking_settings;
mod target_release;
#[cfg(test)]
pub(crate) mod test_utils;
Expand Down
1 change: 1 addition & 0 deletions nexus/db-queries/src/db/datastore/sled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4423,6 +4423,7 @@ pub(in crate::db::datastore) mod test {
auto_restart_policy: Default::default(),
anti_affinity_groups: Vec::new(),
multicast_groups: Vec::new(),
enable_jumbo_frames: false,
},
),
)
Expand Down
Loading