Skip to content

Commit 2e7cf69

Browse files
committed
Attached (External) Subnets
This PR reworks certain aspects of how NAT and gateway layers are constructed to enable attached (external) subnets to function. The primary aim here is that traffic to/from these subnets (owned by the host) do not undergo NAT, and bypass spoof detection as transit IPs would. A few wider changes have been necessary to ensure that these can be attached/detached without breaking any existing transit IPs, and to ensure that traffic originated from an external subnet cannot be directed towards a private VPC recipient.
1 parent e329820 commit 2e7cf69

File tree

37 files changed

+1404
-432
lines changed

37 files changed

+1404
-432
lines changed

.github/buildomat/jobs/opte-api.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ header "analyze std"
2828
ptime -m cargo clippy --all-targets
2929

3030
header "analyze no_std"
31-
ptime -m cargo clippy --no-default-features --all-targets
31+
ptime -m cargo clippy --no-default-features --all-targets -- --deny warnings
3232

3333
header "test"
3434
ptime -m cargo test

.github/buildomat/jobs/opte-ioctl.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ header "check style"
2222
ptime -m cargo +$NIGHTLY fmt -- --check
2323

2424
header "analyze"
25-
ptime -m cargo clippy --all-targets
25+
ptime -m cargo clippy --all-targets -- --deny warnings

.github/buildomat/jobs/opte.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ RUSTDOCFLAGS="-D warnings" ptime -m \
3131
cargo +$NIGHTLY doc --no-default-features --features=api,std,engine,kernel
3232

3333
header "analyze std + api"
34-
ptime -m cargo clippy --all-targets
34+
ptime -m cargo clippy --all-targets -- --deny warnings
3535

3636
header "analyze no_std + engine + kernel"
37-
ptime -m cargo +$NIGHTLY clippy --no-default-features --features engine,kernel
37+
ptime -m cargo +$NIGHTLY clippy --no-default-features --features engine,kernel -- --deny warnings
3838

3939
header "test"
4040
ptime -m cargo test

.github/buildomat/jobs/opteadm.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ header "check style"
3131
ptime -m cargo +$NIGHTLY fmt -- --check
3232

3333
header "analyze"
34-
ptime -m cargo clippy --all-targets
34+
ptime -m cargo clippy --all-targets -- --deny warnings
3535

3636
header "debug build"
3737
ptime -m cargo build

.github/buildomat/jobs/oxide-vpc.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ RUSTDOCFLAGS="-D warnings" ptime -m \
3131
cargo +$NIGHTLY doc --no-default-features --features=api,std,engine,kernel
3232

3333
header "analyze std + api + usdt"
34-
ptime -m cargo clippy --features usdt --all-targets
34+
ptime -m cargo clippy --features usdt --all-targets -- --deny warnings
3535

3636
header "analyze no_std + engine + kernel"
3737
ptime -m cargo +$NIGHTLY clippy --no-default-features --features engine,kernel

.github/buildomat/jobs/xde.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ sha256sum $REL_TGT/xde_link.so > $REL_TGT/xde_link.so.sha256
113113
header "build xde integration tests"
114114
pushd xde-tests
115115
cargo +$NIGHTLY fmt -- --check
116-
cargo clippy --all-targets
116+
cargo clippy --all-targets -- --deny warnings
117117
cargo build --test loopback
118118
loopback_test=$(
119119
cargo build -q --test loopback --message-format=json |\

bench/src/packet.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
// Copyright 2024 Oxide Computer Company
5+
// Copyright 2026 Oxide Computer Company
66

77
use opte::ddi::mblk::MsgBlk;
88
use opte::engine::Direction;
@@ -26,6 +26,7 @@ use opte_test_utils::icmp::gen_icmp_echo;
2626
use opte_test_utils::icmp::gen_icmpv6_echo;
2727
use opte_test_utils::icmp::generate_ndisc;
2828
use opte_test_utils::*;
29+
use std::collections::BTreeMap;
2930

3031
pub type TestCase = (MsgBlk, Direction);
3132

@@ -91,6 +92,8 @@ impl BenchPacket for UlpProcess {
9192
ephemeral_ip: Some("10.60.1.20".parse().unwrap()),
9293
floating_ips: vec![],
9394
},
95+
attached_subnets: BTreeMap::default(),
96+
transit_ips: BTreeMap::default(),
9497
},
9598
ipv6: Ipv6Cfg {
9699
vpc_subnet: "fd00::/64".parse().unwrap(),
@@ -104,6 +107,8 @@ impl BenchPacket for UlpProcess {
104107
ephemeral_ip: Some("2001:db8::2".parse().unwrap()),
105108
floating_ips: vec![],
106109
},
110+
attached_subnets: BTreeMap::default(),
111+
transit_ips: BTreeMap::default(),
107112
},
108113
};
109114

@@ -269,18 +274,13 @@ impl BenchPacketInstance for UlpProcessInstance {
269274
let out_pkt = match self.direction {
270275
Direction::Out => inner_pkt,
271276
Direction::In => {
272-
let bsvc_phys = TestIpPhys {
273-
ip: BS_IP_ADDR,
274-
mac: BS_MAC_ADDR,
275-
vni: Vni::new(BOUNDARY_SERVICES_VNI).unwrap(),
276-
};
277277
let guest_phys = TestIpPhys {
278278
ip: self.cfg.phys_ip,
279279
mac: self.cfg.guest_mac,
280280
vni: self.cfg.vni,
281281
};
282282

283-
encap_external(inner_pkt, bsvc_phys, guest_phys)
283+
encap_external(inner_pkt, *BSVC_PHYS, guest_phys)
284284
}
285285
};
286286

bin/opteadm/src/bin/opteadm.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
// Copyright 2025 Oxide Computer Company
5+
// Copyright 2026 Oxide Computer Company
66

77
use anyhow::Context;
88
use clap::Args;
@@ -70,6 +70,7 @@ use oxide_vpc::print::print_mcast_fwd;
7070
use oxide_vpc::print::print_mcast_subs;
7171
use oxide_vpc::print::print_v2b;
7272
use oxide_vpc::print::print_v2p;
73+
use std::collections::BTreeMap;
7374
use std::io;
7475
use std::io::Write;
7576
use std::str::FromStr;
@@ -403,6 +404,36 @@ enum Command {
403404
#[arg(long = "dir")]
404405
direction: Option<Direction>,
405406
},
407+
408+
/// Give a guest ownership of a given CIDR block.
409+
///
410+
/// This is equivalent to a bidirectional `AllowCidr`, with an exemption
411+
/// from NAT if the subnet is marked as `external`.
412+
///
413+
/// Repeated calls on any given `prefix` will update its configuration.
414+
AttachSubnet {
415+
/// The OPTE port to configure.
416+
#[arg(short)]
417+
port: String,
418+
419+
/// The subnet to attach.
420+
prefix: IpCidr,
421+
422+
/// Marks the subnet as a block of external IPs for which in/outbound
423+
/// NAT should not be performed.
424+
#[arg(long, short)]
425+
external: bool,
426+
},
427+
428+
/// Rescind a guest's ownership of a given CIDR block.
429+
DetachSubnet {
430+
/// The OPTE port to configure.
431+
#[arg(short)]
432+
port: String,
433+
434+
/// The subnet to detach.
435+
prefix: IpCidr,
436+
},
406437
}
407438

408439
#[derive(Debug, Parser)]
@@ -805,6 +836,8 @@ fn main() -> anyhow::Result<()> {
805836
private_ip,
806837
gateway_ip,
807838
external_ips,
839+
attached_subnets: BTreeMap::new(),
840+
transit_ips: BTreeMap::new(),
808841
})
809842
}
810843
IpAddr::Ip6(private_ip) => {
@@ -823,6 +856,8 @@ fn main() -> anyhow::Result<()> {
823856
private_ip,
824857
gateway_ip,
825858
external_ips,
859+
attached_subnets: BTreeMap::new(),
860+
transit_ips: BTreeMap::new(),
826861
})
827862
}
828863
};
@@ -833,9 +868,10 @@ fn main() -> anyhow::Result<()> {
833868
gateway_mac,
834869
vni: vpc_vni,
835870
phys_ip: src_underlay_addr,
871+
dhcp: dhcp.into(),
836872
};
837873

838-
hdl.create_xde(&name, cfg, dhcp.into(), passthrough)?;
874+
hdl.create_xde(&name, cfg, passthrough)?;
839875
}
840876

841877
Command::DeleteXde { name } => {
@@ -1054,6 +1090,14 @@ fn main() -> anyhow::Result<()> {
10541090
})?;
10551091
}
10561092
}
1093+
1094+
Command::AttachSubnet { port, prefix, external } => {
1095+
hdl.attach_subnet(&port, prefix, external)?;
1096+
}
1097+
1098+
Command::DetachSubnet { port, prefix } => {
1099+
hdl.detach_subnet(&port, prefix)?;
1100+
}
10571101
}
10581102

10591103
Ok(())

crates/opte-api/src/cmd.rs

Lines changed: 90 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
// Copyright 2025 Oxide Computer Company
5+
// Copyright 2026 Oxide Computer Company
66

77
use super::API_VERSION;
88
use super::RuleId;
@@ -25,40 +25,95 @@ pub const XDE_IOC_OPTE_CMD: i32 = XDE_IOC as i32 | 0x01;
2525
#[derive(Clone, Copy, Debug)]
2626
#[repr(C)]
2727
pub enum OpteCmd {
28-
ListPorts = 1, // list all ports
29-
AddFwRule = 20, // add firewall rule
30-
RemFwRule = 21, // remove firewall rule
31-
SetFwRules = 22, // set/replace all firewall rules at once
32-
DumpTcpFlows = 30, // dump TCP flows
33-
DumpLayer = 31, // dump the specified Layer
34-
DumpUft = 32, // dump the Unified Flow Table
35-
ListLayers = 33, // list the layers on a given port
36-
ClearUft = 40, // clear the UFT
37-
ClearLft = 41, // clear the given Layer's Flow Table
38-
SetVirt2Phys = 50, // set a v2p mapping
39-
DumpVirt2Phys = 51, // dump the v2p mappings
40-
SetVirt2Boundary = 52, // set a v2b mapping
41-
ClearVirt2Boundary = 53, // clear a v2b mapping
42-
DumpVirt2Boundary = 54, // dump the v2b mappings
43-
ClearVirt2Phys = 55, // clear a v2p mapping
44-
AddRouterEntry = 60, // add a router entry for IP dest
45-
DelRouterEntry = 61, // remove a router entry for IP dest
46-
CreateXde = 70, // create a new xde device
47-
DeleteXde = 71, // delete an xde device
48-
SetXdeUnderlay = 72, // set xde underlay devices
49-
ClearXdeUnderlay = 73, // clear xde underlay devices
50-
SetExternalIps = 80, // set xde external IPs for a port
51-
AllowCidr = 90, // allow ip block through gateway tx/rx
52-
RemoveCidr = 91, // deny ip block through gateway tx/rx
53-
SetMcastForwarding = 100, // set multicast forwarding entries
54-
ClearMcastForwarding = 101, // clear multicast forwarding entries
55-
DumpMcastForwarding = 102, // dump multicast forwarding table
56-
McastSubscribe = 103, // subscribe a port to a multicast group
57-
McastUnsubscribe = 104, // unsubscribe a port from a multicast group
58-
SetMcast2Phys = 105, // set M2P mapping (group -> underlay mcast)
59-
ClearMcast2Phys = 106, // clear M2P mapping
60-
DumpMcastSubscriptions = 107, // dump multicast subscription table
61-
McastUnsubscribeAll = 108, // unsubscribe all ports from a multicast group
28+
/// List all ports.
29+
ListPorts = 1,
30+
31+
/// Add a firewall rule.
32+
AddFwRule = 20,
33+
/// Remove a firewall rule.
34+
RemFwRule = 21,
35+
/// Set/replace all firewall rules at once.
36+
SetFwRules = 22,
37+
38+
/// Read out TCP flows and statistics.
39+
DumpTcpFlows = 30,
40+
/// Read out installed rules and hit counters in a given layer.
41+
DumpLayer = 31,
42+
/// Read out UFT (fastpath) flow entries and their associated counters.
43+
DumpUft = 32,
44+
/// List the layers on a given port.
45+
ListLayers = 33,
46+
47+
/// Clear the UFT (fastpath) for a port.
48+
ClearUft = 40,
49+
/// Clear a layer's flow table.
50+
ClearLft = 41,
51+
52+
/// Set a V2P mapping.
53+
SetVirt2Phys = 50,
54+
/// Read out all V2P mappings.
55+
DumpVirt2Phys = 51,
56+
/// Set a V2B mapping.
57+
SetVirt2Boundary = 52,
58+
/// Remove a V2B mapping.
59+
ClearVirt2Boundary = 53,
60+
/// Read out all V2B mappings.
61+
DumpVirt2Boundary = 54,
62+
/// Remove a V2P mapping.
63+
ClearVirt2Phys = 55,
64+
65+
/// Add a router entry for an IP destination CIDR.
66+
AddRouterEntry = 60,
67+
/// Remove a router entry for an IP destination CIDR.
68+
DelRouterEntry = 61,
69+
70+
/// Create a new XDE device.
71+
///
72+
/// Requires that `SetXdeUnderlay` has been successfully called.
73+
CreateXde = 70,
74+
/// Delete an XDE device.
75+
DeleteXde = 71,
76+
/// Set the physical devices which XDE should transmit over.
77+
SetXdeUnderlay = 72,
78+
/// Unbind the underlay devices.
79+
///
80+
/// Requires that no XDE ports exist.
81+
ClearXdeUnderlay = 73,
82+
83+
/// Set all external IP config for a port.
84+
SetExternalIps = 80,
85+
86+
/// Add a transit IP CIDR to this port's allow list.
87+
///
88+
/// NOOPs if the given CIDR is an attached subnet.
89+
AllowCidr = 90,
90+
/// Remove a transit IP CIDR from this port's allow list.
91+
///
92+
/// NOOPs if the given CIDR is an attached subnet.
93+
RemoveCidr = 91,
94+
/// Add or set the config of an attached subnet.
95+
AttachSubnet = 92,
96+
/// Remove an attached subnet.
97+
DetachSubnet = 93,
98+
99+
/// Set multicast forwarding entries.
100+
SetMcastForwarding = 100,
101+
/// Clear multicast forwarding entries.
102+
ClearMcastForwarding = 101,
103+
/// Read out the multicast forwarding table.
104+
DumpMcastForwarding = 102,
105+
/// Subscribe a port to a multicast group.
106+
McastSubscribe = 103,
107+
/// Unsubscribe a port to a multicast group.
108+
McastUnsubscribe = 104,
109+
/// Set an M2P mapping (group -> underlay mcast).
110+
SetMcast2Phys = 105,
111+
/// Remove an M2P mapping.
112+
ClearMcast2Phys = 106,
113+
/// Read out the table of multicast subscriptions.
114+
DumpMcastSubscriptions = 107,
115+
/// Unsubscribe all ports from a multicast group.
116+
McastUnsubscribeAll = 108,
62117
}
63118

64119
impl TryFrom<c_int> for OpteCmd {

crates/opte-api/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
// Copyright 2025 Oxide Computer Company
5+
// Copyright 2026 Oxide Computer Company
66

77
#![no_std]
88
#![deny(unreachable_patterns)]
@@ -51,7 +51,7 @@ pub use ulp::*;
5151
///
5252
/// We rely on CI and the check-api-version.sh script to verify that
5353
/// this number is incremented anytime the oxide-api code changes.
54-
pub const API_VERSION: u64 = 38;
54+
pub const API_VERSION: u64 = 39;
5555

5656
/// Major version of the OPTE package.
5757
pub const MAJOR_VERSION: u64 = 0;

0 commit comments

Comments
 (0)