Skip to content

Commit a9d9f1e

Browse files
authored
Add Nexus and database support for IPv6 NAT (#8758)
- Renames NAT tables in the database to be IP-family agnostic - Renames NAT-enry-related types to be IP-family agnostic - Adds a generic `IpNet` database model type - Adds handling of IPv6 addresses for NAT entries, for both services and instances - Fixes #5090. Fixes #8749.
1 parent a582b52 commit a9d9f1e

File tree

34 files changed

+674
-580
lines changed

34 files changed

+674
-580
lines changed

common/src/api/external/mod.rs

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ impl JsonSchema for Hostname {
901901
// General types used to implement API resources
902902

903903
/// Identifies a type of API resource
904+
// NOTE: Please keep this enum in alphabetical order.
904905
#[derive(
905906
Clone,
906907
Copy,
@@ -920,77 +921,77 @@ pub enum ResourceType {
920921
AddressLotBlock,
921922
AffinityGroup,
922923
AffinityGroupMember,
923-
AntiAffinityGroup,
924-
AntiAffinityGroupMember,
925924
Alert,
926925
AlertReceiver,
927926
AllowList,
927+
AntiAffinityGroup,
928+
AntiAffinityGroupMember,
928929
AuditLogEntry,
929930
BackgroundTask,
930-
BgpConfig,
931931
BgpAnnounceSet,
932+
BgpConfig,
932933
Blueprint,
933-
Fleet,
934-
Silo,
935-
SiloUser,
936-
SiloGroup,
937-
SiloQuotas,
938-
IdentityProvider,
939-
SamlIdentityProvider,
940-
SshKey,
941934
Certificate,
942935
ConsoleSession,
943-
DeviceAuthRequest,
944-
DeviceAccessToken,
945-
Project,
946936
Dataset,
937+
DeviceAccessToken,
938+
DeviceAuthRequest,
947939
Disk,
940+
Fleet,
941+
FloatingIp,
942+
IdentityProvider,
948943
Image,
949-
SiloImage,
950-
ProjectImage,
951944
Instance,
952-
LoopbackAddress,
953-
SiloAuthSettings,
954-
SwitchPortSettings,
955-
SupportBundle,
956-
IpPool,
957-
IpPoolResource,
958945
InstanceNetworkInterface,
959946
InternetGateway,
960-
InternetGatewayIpPool,
961947
InternetGatewayIpAddress,
948+
InternetGatewayIpPool,
949+
IpPool,
950+
IpPoolResource,
951+
LldpLinkConfig,
952+
LoopbackAddress,
953+
MetricProducer,
954+
NatEntry,
955+
Oximeter,
962956
PhysicalDisk,
957+
Probe,
958+
ProbeNetworkInterface,
959+
Project,
960+
ProjectImage,
963961
Rack,
962+
RoleBuiltin,
963+
RouterRoute,
964+
SagaDbg,
965+
SamlIdentityProvider,
964966
Service,
965967
ServiceNetworkInterface,
968+
Silo,
969+
SiloAuthSettings,
970+
SiloGroup,
971+
SiloImage,
972+
SiloQuotas,
973+
SiloUser,
966974
Sled,
967975
SledInstance,
968976
SledLedger,
969-
Switch,
970-
SagaDbg,
971977
Snapshot,
972-
Volume,
973-
Vpc,
974-
VpcFirewallRule,
975-
VpcSubnet,
976-
VpcRouter,
977-
RouterRoute,
978-
Oximeter,
979-
MetricProducer,
980-
RoleBuiltin,
981-
TufRepo,
978+
SshKey,
979+
SupportBundle,
980+
Switch,
981+
SwitchPort,
982+
SwitchPortSettings,
982983
TufArtifact,
984+
TufRepo,
983985
TufTrustRoot,
984-
SwitchPort,
985986
UserBuiltin,
986-
Zpool,
987987
Vmm,
988-
Ipv4NatEntry,
989-
FloatingIp,
990-
Probe,
991-
ProbeNetworkInterface,
992-
LldpLinkConfig,
988+
Volume,
989+
Vpc,
990+
VpcFirewallRule,
991+
VpcRouter,
992+
VpcSubnet,
993993
WebhookSecret,
994+
Zpool,
994995
}
995996

996997
// IDENTITY METADATA

dev-tools/omdb/src/bin/omdb/nexus.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ async fn cmd_nexus_background_tasks_show(
928928
"dns_config_external",
929929
"dns_servers_external",
930930
"dns_propagation_external",
931-
"nat_v4_garbage_collector",
931+
"nat_garbage_collector",
932932
"blueprint_loader",
933933
"blueprint_executor",
934934
] {

dev-tools/omdb/tests/env.out

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ task: "metrics_producer_gc"
128128
unregisters Oximeter metrics producers that have not renewed their lease
129129

130130

131-
task: "nat_v4_garbage_collector"
132-
prunes soft-deleted IPV4 NAT entries from ipv4_nat_entry table based on a
131+
task: "nat_garbage_collector"
132+
prunes soft-deleted NAT entries from nat_entry table based on a
133133
predetermined retention policy
134134

135135

@@ -336,8 +336,8 @@ task: "metrics_producer_gc"
336336
unregisters Oximeter metrics producers that have not renewed their lease
337337

338338

339-
task: "nat_v4_garbage_collector"
340-
prunes soft-deleted IPV4 NAT entries from ipv4_nat_entry table based on a
339+
task: "nat_garbage_collector"
340+
prunes soft-deleted NAT entries from nat_entry table based on a
341341
predetermined retention policy
342342

343343

@@ -531,8 +531,8 @@ task: "metrics_producer_gc"
531531
unregisters Oximeter metrics producers that have not renewed their lease
532532

533533

534-
task: "nat_v4_garbage_collector"
535-
prunes soft-deleted IPV4 NAT entries from ipv4_nat_entry table based on a
534+
task: "nat_garbage_collector"
535+
prunes soft-deleted NAT entries from nat_entry table based on a
536536
predetermined retention policy
537537

538538

dev-tools/omdb/tests/successes.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ task: "metrics_producer_gc"
340340
unregisters Oximeter metrics producers that have not renewed their lease
341341

342342

343-
task: "nat_v4_garbage_collector"
344-
prunes soft-deleted IPV4 NAT entries from ipv4_nat_entry table based on a
343+
task: "nat_garbage_collector"
344+
prunes soft-deleted NAT entries from nat_entry table based on a
345345
predetermined retention policy
346346

347347

@@ -481,7 +481,7 @@ task: "dns_propagation_external"
481481
[::1]:REDACTED_PORT success
482482

483483

484-
task: "nat_v4_garbage_collector"
484+
task: "nat_garbage_collector"
485485
configured period: every <REDACTED_DURATION>s
486486
last completed activation: <REDACTED ITERATIONS>, triggered by a periodic timer firing
487487
started at <REDACTED_TIMESTAMP> (<REDACTED DURATION>s ago) and ran for <REDACTED DURATION>ms
@@ -991,7 +991,7 @@ task: "dns_propagation_external"
991991
[::1]:REDACTED_PORT success
992992

993993

994-
task: "nat_v4_garbage_collector"
994+
task: "nat_garbage_collector"
995995
configured period: every <REDACTED_DURATION>s
996996
currently executing: no
997997
last completed activation: <REDACTED ITERATIONS>, triggered by a periodic timer firing

nexus/db-model/src/ipnet.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use diesel::backend::Backend;
6+
use diesel::deserialize;
7+
use diesel::deserialize::FromSql;
8+
use diesel::pg::Pg;
9+
use diesel::serialize;
10+
use diesel::serialize::ToSql;
11+
use diesel::sql_types;
12+
use ipnetwork::IpNetwork;
13+
use serde::Deserialize;
14+
use serde::Serialize;
15+
16+
#[derive(
17+
Clone,
18+
Copy,
19+
Debug,
20+
Eq,
21+
PartialEq,
22+
AsExpression,
23+
FromSqlRow,
24+
Serialize,
25+
Deserialize,
26+
)]
27+
#[diesel(sql_type = sql_types::Inet)]
28+
pub enum IpNet {
29+
V4(crate::Ipv4Net),
30+
V6(crate::Ipv6Net),
31+
}
32+
33+
impl ::std::fmt::Display for IpNet {
34+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35+
match self {
36+
IpNet::V4(inner) => inner.fmt(f),
37+
IpNet::V6(inner) => inner.fmt(f),
38+
}
39+
}
40+
}
41+
42+
impl From<IpNet> for ::std::net::IpAddr {
43+
fn from(value: IpNet) -> Self {
44+
match value {
45+
IpNet::V4(inner) => ::std::net::IpAddr::V4(inner.addr()),
46+
IpNet::V6(inner) => ::std::net::IpAddr::V6(inner.addr()),
47+
}
48+
}
49+
}
50+
51+
impl From<ipnetwork::IpNetwork> for IpNet {
52+
fn from(value: ipnetwork::IpNetwork) -> Self {
53+
match value {
54+
IpNetwork::V4(ipv4) => Self::from(oxnet::Ipv4Net::from(ipv4)),
55+
IpNetwork::V6(ipv6) => Self::from(oxnet::Ipv6Net::from(ipv6)),
56+
}
57+
}
58+
}
59+
60+
impl From<oxnet::Ipv4Net> for IpNet {
61+
fn from(value: oxnet::Ipv4Net) -> Self {
62+
Self::V4(crate::Ipv4Net::from(value))
63+
}
64+
}
65+
66+
impl From<oxnet::Ipv6Net> for IpNet {
67+
fn from(value: oxnet::Ipv6Net) -> Self {
68+
Self::V6(crate::Ipv6Net::from(value))
69+
}
70+
}
71+
72+
impl From<oxnet::IpNet> for IpNet {
73+
fn from(value: oxnet::IpNet) -> Self {
74+
match value {
75+
oxnet::IpNet::V4(ipv4_net) => {
76+
Self::V4(crate::Ipv4Net::from(ipv4_net))
77+
}
78+
oxnet::IpNet::V6(ipv6_net) => {
79+
Self::V6(crate::Ipv6Net::from(ipv6_net))
80+
}
81+
}
82+
}
83+
}
84+
85+
impl ToSql<sql_types::Inet, Pg> for IpNet {
86+
fn to_sql<'a>(
87+
&'a self,
88+
out: &mut serialize::Output<'a, '_, Pg>,
89+
) -> serialize::Result {
90+
let inner = match self {
91+
IpNet::V4(inner) => IpNetwork::V4(inner.0.into()),
92+
IpNet::V6(inner) => IpNetwork::V6(inner.0.into()),
93+
};
94+
<IpNetwork as ToSql<sql_types::Inet, Pg>>::to_sql(
95+
&inner,
96+
&mut out.reborrow(),
97+
)
98+
}
99+
}
100+
101+
impl<DB> FromSql<sql_types::Inet, DB> for IpNet
102+
where
103+
DB: Backend,
104+
IpNetwork: FromSql<sql_types::Inet, DB>,
105+
{
106+
fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
107+
let inet = IpNetwork::from_sql(bytes)?;
108+
match inet {
109+
IpNetwork::V4(net) => Ok(Self::V4(crate::Ipv4Net(net.into()))),
110+
IpNetwork::V6(net) => Ok(Self::V6(crate::Ipv6Net(net.into()))),
111+
}
112+
}
113+
}

nexus/db-model/src/ipv4_nat_entry.rs

Lines changed: 0 additions & 76 deletions
This file was deleted.

0 commit comments

Comments
 (0)