Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VPC Subnet Routing [2/2] -- Custom Routers and NIC 'transit IP' lists #5823

Merged
merged 77 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
76106b1
Clear XDE underlay when destroying virtual hardware
FelixMcFelix Apr 23, 2024
0afee1b
Merge branch 'main' into felixmcfelix/opte-underlay-lock
FelixMcFelix May 21, 2024
94e1808
Pull in latest OPTE after merge.
FelixMcFelix May 21, 2024
b67f416
Bump OPTE and related.
FelixMcFelix May 21, 2024
5f7cfa8
Compat with newer OPTE, more believable router rules
FelixMcFelix May 21, 2024
16e0107
VPC Subnet route reconcile.
FelixMcFelix May 15, 2024
22b71bb
We now have valid, sane, default system routes
FelixMcFelix May 15, 2024
160853b
Start refreshing API specs
FelixMcFelix May 15, 2024
034dd0f
Iterating.
FelixMcFelix May 16, 2024
87d9b26
Route resolution (but not actual installation)
FelixMcFelix May 17, 2024
568f44c
Wrong ID in router initialisation.
FelixMcFelix May 17, 2024
2a25d74
Rule insert/delete with OPTE.
FelixMcFelix May 17, 2024
c718c8d
Correctly instantiate router rules if existing
FelixMcFelix May 17, 2024
06eaaab
Feed Clippy.
FelixMcFelix May 20, 2024
38beadd
Comment adapted.
FelixMcFelix May 20, 2024
17489cb
The backing code for a generational RPW
FelixMcFelix May 20, 2024
006b1ca
Iterating.
FelixMcFelix May 21, 2024
c7de875
Trigger RPW in all the right spots.
FelixMcFelix May 21, 2024
40edbc8
Unpublish VPC routers API.
FelixMcFelix May 22, 2024
3b3abb1
Fixup broken tests.
FelixMcFelix May 22, 2024
be9f8ab
Accidental local state...
FelixMcFelix May 22, 2024
f433b38
Unsubscribe routes from sled when ports are removed.
FelixMcFelix May 22, 2024
62ca9f0
Migration query for subnet route creation.
FelixMcFelix May 23, 2024
2c06ff4
Rework migration slightly.
FelixMcFelix May 23, 2024
0e8d1ad
Bump OPTE to include latest perf work.
FelixMcFelix May 23, 2024
7b32e09
Merge branch 'main' into felixmcfelix/opte-underlay-lock
FelixMcFelix May 23, 2024
f7646ef
Merge branch 'felixmcfelix/opte-underlay-lock' into felixmcfelix/vpc-…
FelixMcFelix May 23, 2024
2537222
Self-review pt.1.
FelixMcFelix May 23, 2024
f217bd1
Self-review pt.2.
FelixMcFelix May 23, 2024
b549044
Test route resolution.
FelixMcFelix May 23, 2024
f02535e
Accidentally ended up on the wrong maghemite.
FelixMcFelix May 24, 2024
880378a
Hook VPC checks into sim-sled-agent, instance networking tests.
FelixMcFelix May 24, 2024
08c982e
Correctly cleanup after new tests...
FelixMcFelix May 24, 2024
821e241
Allow bind of subnet to custom router in create/update
FelixMcFelix May 24, 2024
9c68888
Fix VpcRouter field order, test usual attachment behaviour
FelixMcFelix May 28, 2024
e886d16
Fix custom router listing.
FelixMcFelix May 28, 2024
e6fe817
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix May 28, 2024
e78c51f
First shot at spoof-prevention prevention.
FelixMcFelix May 29, 2024
c1dc6d0
Test router attach swap, cleanup tests.
FelixMcFelix May 29, 2024
0f0dcb6
Validate custom, dest/target pairs on route create
FelixMcFelix May 29, 2024
3d17960
Visit + test allowed routes and modification semantics in-depth.
FelixMcFelix May 29, 2024
4c40916
Don't break parsing NICs from old blueprints
FelixMcFelix May 29, 2024
536b40c
Minor fmt + lint tweaks.
FelixMcFelix May 29, 2024
83b1710
Fixup unexpected authz endpoints.
FelixMcFelix May 29, 2024
7413adf
Last big test, cutesier test data names.
FelixMcFelix May 30, 2024
bd7294c
Fixup one test.
FelixMcFelix May 30, 2024
e3b7b90
Self-review.
FelixMcFelix May 31, 2024
321cb16
Merge branch 'main' into felixmcfelix/vpc-subnet-routing
FelixMcFelix Jun 3, 2024
a8415b3
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 3, 2024
f21ef51
Merge branch 'main' into felixmcfelix/vpc-subnet-routing
FelixMcFelix Jun 13, 2024
87cf88e
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 13, 2024
cca764f
Bump image.
FelixMcFelix Jun 13, 2024
543cac4
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 13, 2024
bf3ffb0
Handle greater specificity of rule addition.
FelixMcFelix Jun 13, 2024
2425016
Forgot some maghemite SHAs...
FelixMcFelix Jun 13, 2024
8e005a2
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 13, 2024
feb455f
Merge branch 'main' into felixmcfelix/vpc-subnet-routing
FelixMcFelix Jun 21, 2024
30e4043
Minor fixes post-merge.
FelixMcFelix Jun 21, 2024
0057228
Review feedback.
FelixMcFelix Jun 21, 2024
a63b8b0
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 21, 2024
28cb739
One or two UUID-types missed...
FelixMcFelix Jun 21, 2024
992b9b5
More liberal use of `#[serde(default)]`
FelixMcFelix Jun 21, 2024
ab7223b
Accidentally a line.
FelixMcFelix Jun 21, 2024
2568e2c
Especially good at EXPECTORATE-ing
FelixMcFelix Jun 21, 2024
d747d01
Again.
FelixMcFelix Jun 21, 2024
c1e5e75
Review feedback: clearer explanation of `RouteDestination`
FelixMcFelix Jun 21, 2024
15bb2ee
Merge branch 'main' into felixmcfelix/vpc-subnet-routing
FelixMcFelix Jun 24, 2024
3766244
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 24, 2024
0ab6483
Slight adjustments to `destination` docstrings
FelixMcFelix Jun 25, 2024
8162a23
Review feedback: typed RouterKind instead of Option abuse
FelixMcFelix Jun 26, 2024
e1971bc
Bump Maghemite.
FelixMcFelix Jun 26, 2024
899d367
Merge branch 'main' into felixmcfelix/vpc-subnet-routing
FelixMcFelix Jun 26, 2024
70263a2
Better conflict resolution on Nexus-managed subnet route names
FelixMcFelix Jun 26, 2024
9b46a28
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 26, 2024
62de75e
Unearthed a nice li'l bug during migration on london
FelixMcFelix Jun 26, 2024
93b073c
Merge branch 'felixmcfelix/vpc-subnet-routing' into felixmcfelix/vpc-…
FelixMcFelix Jun 26, 2024
2bd4bd7
Merge branch 'main' into felixmcfelix/vpc-subnets-user
FelixMcFelix Jun 26, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock

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

10 changes: 7 additions & 3 deletions common/src/api/external/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1407,14 +1407,13 @@ pub struct RouterRoute {
/// common identifying metadata
#[serde(flatten)]
pub identity: IdentityMetadata,

/// The ID of the VPC Router to which the route belongs
pub vpc_router_id: Uuid,

/// Describes the kind of router. Set at creation. `read-only`
pub kind: RouterRouteKind,

/// The location that matched packets should be forwarded to.
pub target: RouteTarget,
/// Selects which traffic this routing rule will apply to.
pub destination: RouteDestination,
}

Expand Down Expand Up @@ -1979,6 +1978,11 @@ pub struct InstanceNetworkInterface {
/// True if this interface is the primary for the instance to which it's
/// attached.
pub primary: bool,

/// A set of additional networks that this interface may send and
/// receive traffic on.
#[serde(default)]
pub transit_ips: Vec<IpNet>,
FelixMcFelix marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(
Expand Down
2 changes: 2 additions & 0 deletions common/src/api/internal/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub struct NetworkInterface {
pub vni: Vni,
pub primary: bool,
pub slot: u8,
#[serde(default)]
pub transit_ips: Vec<IpNet>,
}

/// An IP address and port range used for source NAT, i.e., making
Expand Down
35 changes: 35 additions & 0 deletions illumos-utils/src/opte/port_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,41 @@ impl PortManager {
}
}

// If there are any transit IPs set, allow them through.
// TODO: Currently set only in initial state.
// This, external IPs, and cfg'able state
// (DHCP?) are probably worth being managed by an RPW.
for block in &nic.transit_ips {
#[cfg(target_os = "illumos")]
{
use oxide_vpc::api::Direction;

// In principle if this were an operation on an existing
// port, we would explicitly undo the In addition if the
// Out addition fails.
// However, failure here will just destroy the port
// outright -- this should only happen if an excessive
// number of rules are specified.
hdl.allow_cidr(
&port_name,
super::net_to_cidr(*block),
Direction::In,
)?;
hdl.allow_cidr(
&port_name,
super::net_to_cidr(*block),
Direction::Out,
)?;
}

debug!(
self.inner.log,
"Added CIDR to in/out allowlist";
"port_name" => &port_name,
"cidr" => ?block,
);
}

info!(
self.inner.log,
"Created OPTE port";
Expand Down
4 changes: 4 additions & 0 deletions nexus/db-model/src/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,8 @@ pub trait DatastoreAttachTargetConfig<ResourceType>:
type ResourceTimeDeletedColumn: Column<Table = <Self::ResourceIdColumn as Column>::Table>
+ Default
+ ExpressionMethods;

/// Controls whether a resource may be attached to a new collection without
/// first being explicitly detached from the previous one
const ALLOW_FROM_ATTACHED: bool = false;
}
26 changes: 23 additions & 3 deletions nexus/db-model/src/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use chrono::DateTime;
use chrono::Utc;
use db_macros::Resource;
use diesel::AsChangeset;
use ipnetwork::IpNetwork;
use ipnetwork::NetworkSize;
use nexus_types::external_api::params;
use nexus_types::identity::Resource;
Expand Down Expand Up @@ -64,11 +65,13 @@ pub struct NetworkInterface {
//
// If user requests an address of either kind, give exactly that and not the other.
// If neither is specified, auto-assign one of each?
pub ip: ipnetwork::IpNetwork,
pub ip: IpNetwork,

pub slot: SqlU8,
#[diesel(column_name = is_primary)]
pub primary: bool,

pub transit_ips: Vec<IpNetwork>,
}

impl NetworkInterface {
Expand Down Expand Up @@ -102,6 +105,7 @@ impl NetworkInterface {
vni: external::Vni::try_from(0).unwrap(),
primary: self.primary,
slot: *self.slot,
transit_ips: self.transit_ips.into_iter().map(Into::into).collect(),
}
}
}
Expand All @@ -122,11 +126,13 @@ pub struct InstanceNetworkInterface {
pub subnet_id: Uuid,

pub mac: MacAddr,
pub ip: ipnetwork::IpNetwork,
pub ip: IpNetwork,

pub slot: SqlU8,
#[diesel(column_name = is_primary)]
pub primary: bool,

pub transit_ips: Vec<IpNetwork>,
}

/// Service Network Interface DB model.
Expand All @@ -145,7 +151,7 @@ pub struct ServiceNetworkInterface {
pub subnet_id: Uuid,

pub mac: MacAddr,
pub ip: ipnetwork::IpNetwork,
pub ip: IpNetwork,

pub slot: SqlU8,
#[diesel(column_name = is_primary)]
Expand Down Expand Up @@ -242,6 +248,7 @@ impl NetworkInterface {
ip: self.ip,
slot: self.slot,
primary: self.primary,
transit_ips: self.transit_ips,
}
}

Expand Down Expand Up @@ -290,6 +297,7 @@ impl From<InstanceNetworkInterface> for NetworkInterface {
ip: iface.ip,
slot: iface.slot,
primary: iface.primary,
transit_ips: iface.transit_ips,
}
}
}
Expand All @@ -313,6 +321,7 @@ impl From<ServiceNetworkInterface> for NetworkInterface {
ip: iface.ip,
slot: iface.slot,
primary: iface.primary,
transit_ips: vec![],
}
}
}
Expand Down Expand Up @@ -460,6 +469,7 @@ pub struct NetworkInterfaceUpdate {
pub time_modified: DateTime<Utc>,
#[diesel(column_name = is_primary)]
pub primary: Option<bool>,
pub transit_ips: Vec<IpNetwork>,
}

impl From<InstanceNetworkInterface> for external::InstanceNetworkInterface {
Expand All @@ -472,6 +482,11 @@ impl From<InstanceNetworkInterface> for external::InstanceNetworkInterface {
ip: iface.ip.ip(),
mac: *iface.mac,
primary: iface.primary,
transit_ips: iface
.transit_ips
.into_iter()
.map(Into::into)
.collect(),
}
}
}
Expand All @@ -484,6 +499,11 @@ impl From<params::InstanceNetworkInterfaceUpdate> for NetworkInterfaceUpdate {
description: params.identity.description,
time_modified: Utc::now(),
primary,
transit_ips: params
.transit_ips
.into_iter()
.map(Into::into)
.collect(),
}
}
}
1 change: 1 addition & 0 deletions nexus/db-model/src/omicron_zone_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,7 @@ impl OmicronZoneNic {
vni: omicron_common::api::external::Vni::try_from(*self.vni)
.context("parsing VNI")?,
subnet: self.subnet.into(),
transit_ips: vec![],
})
}
}
2 changes: 2 additions & 0 deletions nexus/db-model/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ table! {
ip -> Inet,
slot -> Int2,
is_primary -> Bool,
transit_ips -> Array<Inet>,
}
}

Expand All @@ -529,6 +530,7 @@ table! {
ip -> Inet,
slot -> Int2,
is_primary -> Bool,
transit_ips -> Array<Inet>,
}
}
joinable!(instance_network_interface -> instance (instance_id));
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 @@ -17,7 +17,7 @@ use std::collections::BTreeMap;
///
/// 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: SemverVersion = SemverVersion::new(78, 0, 0);
pub const SCHEMA_VERSION: SemverVersion = SemverVersion::new(79, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -29,6 +29,7 @@ static KNOWN_VERSIONS: Lazy<Vec<KnownVersion>> = Lazy::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(79, "nic-spoof-allow"),
KnownVersion::new(78, "vpc-subnet-routing"),
KnownVersion::new(77, "remove-view-for-v2p-mappings"),
KnownVersion::new(76, "lookup-region-snapshot-by-snapshot-id"),
Expand Down
18 changes: 16 additions & 2 deletions nexus/db-model/src/vpc_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

use super::{impl_enum_type, Generation, Name, RouterRoute};
use crate::collection::DatastoreCollectionConfig;
use crate::schema::{router_route, vpc_router};
use crate::schema::{router_route, vpc_router, vpc_subnet};
use crate::{DatastoreAttachTargetConfig, VpcSubnet};
use chrono::{DateTime, Utc};
use db_macros::Resource;
use nexus_types::external_api::params;
Expand Down Expand Up @@ -41,8 +42,8 @@ pub struct VpcRouter {
#[diesel(embed)]
identity: VpcRouterIdentity,

pub vpc_id: Uuid,
pub kind: VpcRouterKind,
pub vpc_id: Uuid,
pub rcgen: Generation,
pub resolved_version: i64,
}
Expand Down Expand Up @@ -99,3 +100,16 @@ impl From<params::VpcRouterUpdate> for VpcRouterUpdate {
}
}
}

impl DatastoreAttachTargetConfig<VpcSubnet> for VpcRouter {
type Id = Uuid;

type CollectionIdColumn = vpc_router::dsl::id;
type CollectionTimeDeletedColumn = vpc_router::dsl::time_deleted;

type ResourceIdColumn = vpc_subnet::dsl::id;
type ResourceCollectionIdColumn = vpc_subnet::dsl::custom_router_id;
type ResourceTimeDeletedColumn = vpc_subnet::dsl::time_deleted;

const ALLOW_FROM_ATTACHED: bool = true;
}
26 changes: 20 additions & 6 deletions nexus/db-queries/src/db/collection_attach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,26 @@ pub trait DatastoreAttachTarget<ResourceType>:
.filter(collection_table().primary_key().eq(collection_id))
.filter(Self::CollectionTimeDeletedColumn::default().is_null()),
);
let resource_query = Box::new(
resource_query
.filter(resource_table().primary_key().eq(resource_id))
.filter(Self::ResourceTimeDeletedColumn::default().is_null())
.filter(Self::ResourceCollectionIdColumn::default().is_null()),
);
let resource_query = if Self::ALLOW_FROM_ATTACHED {
Box::new(
resource_query
.filter(resource_table().primary_key().eq(resource_id))
.filter(
Self::ResourceTimeDeletedColumn::default().is_null(),
),
)
} else {
Box::new(
resource_query
.filter(resource_table().primary_key().eq(resource_id))
.filter(
Self::ResourceTimeDeletedColumn::default().is_null(),
)
.filter(
Self::ResourceCollectionIdColumn::default().is_null(),
),
)
};

let update_resource_statement = update
.into_boxed()
Expand Down
3 changes: 3 additions & 0 deletions nexus/db-queries/src/db/datastore/network_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct NicInfo {
vni: db::model::Vni,
primary: bool,
slot: i16,
transit_ips: Vec<ipnetwork::IpNetwork>,
}

impl From<NicInfo> for omicron_common::api::internal::shared::NetworkInterface {
Expand Down Expand Up @@ -92,6 +93,7 @@ impl From<NicInfo> for omicron_common::api::internal::shared::NetworkInterface {
vni: nic.vni.0,
primary: nic.primary,
slot: u8::try_from(nic.slot).unwrap(),
transit_ips: nic.transit_ips.iter().map(|v| (*v).into()).collect(),
}
}
}
Expand Down Expand Up @@ -502,6 +504,7 @@ impl DataStore {
vpc::vni,
network_interface::is_primary,
network_interface::slot,
network_interface::transit_ips,
))
.get_results_async::<NicInfo>(
&*self.pool_connection_authorized(opctx).await?,
Expand Down
Loading
Loading