Skip to content

Commit ff6d24a

Browse files
authored
Support multicast with sp-sim (#7545)
Previously the simulated SP did not truly support listening in a multicast group. This commit changes the network configuration for the simulated SP so that either "simulated" or "real" is explicitly configured: - if "simulated", then most of the current behaviour is preserved: listen on a bind address but don't join a multicast group. Note: the current behaviour when `multicast_addr` is supplied is incorrect because without the interface index matching the interface that is physically connected to MGS (or faux-mgs), it doesn't work. - if "real", then require all the necessary parameters to correctly configure joining a multicast group for an interface, and set it up.
1 parent 1196d42 commit ff6d24a

File tree

11 files changed

+199
-67
lines changed

11 files changed

+199
-67
lines changed

Cargo.lock

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ nexus-test-interface = { path = "nexus/test-interface" }
494494
nexus-test-utils-macros = { path = "nexus/test-utils-macros" }
495495
nexus-test-utils = { path = "nexus/test-utils" }
496496
nexus-types = { path = "nexus/types" }
497+
nix = { version = "0.29", features = ["net"] }
497498
nom = "7.1.3"
498499
num-integer = "0.1.46"
499500
num = { version = "0.4.3", default-features = false, features = [ "libm" ] }

gateway-test-utils/configs/sp_sim_config.test.toml

+32-8
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@
88
# concurrently.
99
#
1010
[[simulated_sps.sidecar]]
11-
multicast_addr = "::1"
12-
bind_addrs = ["[::1]:0", "[::1]:0"]
1311
serial_number = "SimSidecar0"
1412
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
1513
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000000"
1614

15+
[[simulated_sps.sidecar.network_config]]
16+
[simulated_sps.sidecar.network_config.simulated]
17+
bind_addr = "[::1]:0"
18+
19+
[[simulated_sps.sidecar.network_config]]
20+
[simulated_sps.sidecar.network_config.simulated]
21+
bind_addr = "[::1]:0"
22+
1723
[[simulated_sps.sidecar.components]]
1824
id = "dev-0"
1925
device = "fake-tmp-sensor"
@@ -35,19 +41,31 @@ sensors = [
3541
]
3642

3743
[[simulated_sps.sidecar]]
38-
multicast_addr = "::1"
39-
bind_addrs = ["[::1]:0", "[::1]:0"]
4044
serial_number = "SimSidecar1"
4145
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
4246
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000001"
4347

48+
[[simulated_sps.sidecar.network_config]]
49+
[simulated_sps.sidecar.network_config.simulated]
50+
bind_addr = "[::1]:0"
51+
52+
[[simulated_sps.sidecar.network_config]]
53+
[simulated_sps.sidecar.network_config.simulated]
54+
bind_addr = "[::1]:0"
55+
4456
[[simulated_sps.gimlet]]
45-
multicast_addr = "::1"
46-
bind_addrs = ["[::1]:0", "[::1]:0"]
4757
serial_number = "SimGimlet00"
4858
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
4959
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000002"
5060

61+
[[simulated_sps.gimlet.network_config]]
62+
[simulated_sps.gimlet.network_config.simulated]
63+
bind_addr = "[::1]:0"
64+
65+
[[simulated_sps.gimlet.network_config]]
66+
[simulated_sps.gimlet.network_config.simulated]
67+
bind_addr = "[::1]:0"
68+
5169
[[simulated_sps.gimlet.components]]
5270
id = "sp3-host-cpu"
5371
device = "sp3-host-cpu"
@@ -151,12 +169,18 @@ sensors = [
151169

152170

153171
[[simulated_sps.gimlet]]
154-
multicast_addr = "::1"
155-
bind_addrs = ["[::1]:0", "[::1]:0"]
156172
serial_number = "SimGimlet01"
157173
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
158174
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000003"
159175

176+
[[simulated_sps.gimlet.network_config]]
177+
[simulated_sps.gimlet.network_config.simulated]
178+
bind_addr = "[::1]:0"
179+
180+
[[simulated_sps.gimlet.network_config]]
181+
[simulated_sps.gimlet.network_config.simulated]
182+
bind_addr = "[::1]:0"
183+
160184
[[simulated_sps.gimlet.components]]
161185
id = "sp3-host-cpu"
162186
device = "sp3-host-cpu"

smf/sp-sim/config.toml

+23-6
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,31 @@
33
#
44

55
[[simulated_sps.sidecar]]
6-
multicast_addr = "ff15:0:1de::0"
7-
bind_addrs = ["[::]:33300", "[::]:33301"]
86
serial_number = "SimSidecar0"
97
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
108
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000000"
119

10+
[[simulated_sps.sidecar.network_config]]
11+
[simulated_sps.sidecar.network_config.simulated]
12+
bind_addr = "[::1]:33300"
13+
14+
[[simulated_sps.sidecar.network_config]]
15+
[simulated_sps.sidecar.network_config.simulated]
16+
bind_addr = "[::1]:33301"
1217

1318
[[simulated_sps.gimlet]]
14-
multicast_addr = "ff15:0:1de::1"
15-
bind_addrs = ["[::]:33310", "[::]:33311"]
1619
serial_number = "SimGimlet0"
1720
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
1821
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000001"
1922

23+
[[simulated_sps.gimlet.network_config]]
24+
[simulated_sps.gimlet.network_config.simulated]
25+
bind_addr = "[::1]:33310"
26+
27+
[[simulated_sps.gimlet.network_config]]
28+
[simulated_sps.gimlet.network_config.simulated]
29+
bind_addr = "[::1]:33311"
30+
2031
[[simulated_sps.gimlet.components]]
2132
id = "sp3-host-cpu"
2233
device = "sp3-host-cpu"
@@ -26,12 +37,18 @@ presence = "Present"
2637
serial_console = "[::1]:33312"
2738

2839
[[simulated_sps.gimlet]]
29-
multicast_addr = "ff15:0:1de::2"
30-
bind_addrs = ["[::]:33320", "[::]:33321"]
3140
serial_number = "SimGimlet1"
3241
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
3342
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000002"
3443

44+
[[simulated_sps.gimlet.network_config]]
45+
[simulated_sps.gimlet.network_config.simulated]
46+
bind_addr = "[::1]:33320"
47+
48+
[[simulated_sps.gimlet.network_config]]
49+
[simulated_sps.gimlet.network_config.simulated]
50+
bind_addr = "[::1]:33321"
51+
3552
[[simulated_sps.gimlet.components]]
3653
id = "sp3-host-cpu"
3754
device = "sp3-host-cpu"

sp-sim/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ thiserror.workspace = true
2424
tokio = { workspace = true, features = [ "full" ] }
2525
toml.workspace = true
2626
omicron-workspace-hack.workspace = true
27+
nix.workspace = true
2728

2829
[[bin]]
2930
name = "sp-sim"

sp-sim/examples/config.toml

+24-6
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,31 @@
33
#
44

55
[[simulated_sps.sidecar]]
6-
multicast_addr = "ff15:0:1de::0"
7-
bind_addrs = ["[::]:33300", "[::]:33301"]
86
serial_number = "SimSidecar0"
97
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
108
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000000"
119

10+
[[simulated_sps.sidecar.network_config]]
11+
[simulated_sps.sidecar.network_config.simulated]
12+
bind_addr = "[::1]:33300"
13+
14+
[[simulated_sps.sidecar.network_config]]
15+
[simulated_sps.sidecar.network_config.simulated]
16+
bind_addr = "[::1]:33301"
17+
1218
[[simulated_sps.gimlet]]
13-
multicast_addr = "ff15:0:1de::1"
14-
bind_addrs = ["[::]:33310", "[::]:33311"]
1519
serial_number = "SimGimlet0"
1620
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
1721
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000001"
1822

23+
[[simulated_sps.gimlet.network_config]]
24+
[simulated_sps.gimlet.network_config.simulated]
25+
bind_addr = "[::1]:33310"
26+
27+
[[simulated_sps.gimlet.network_config]]
28+
[simulated_sps.gimlet.network_config.simulated]
29+
bind_addr = "[::1]:33311"
30+
1931
[[simulated_sps.gimlet.components]]
2032
id = "sp3-host-cpu"
2133
device = "sp3-host-cpu"
@@ -45,12 +57,18 @@ sensors = [
4557
]
4658

4759
[[simulated_sps.gimlet]]
48-
multicast_addr = "ff15:0:1de::2"
49-
bind_addrs = ["[::]:33320", "[::]:33321"]
5060
serial_number = "SimGimlet1"
5161
manufacturing_root_cert_seed = "01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de01de"
5262
device_id_cert_seed = "01de000000000000000000000000000000000000000000000000000000000002"
5363

64+
[[simulated_sps.gimlet.network_config]]
65+
[simulated_sps.gimlet.network_config.simulated]
66+
bind_addr = "[::1]:33320"
67+
68+
[[simulated_sps.gimlet.network_config]]
69+
[simulated_sps.gimlet.network_config.simulated]
70+
bind_addr = "[::1]:33321"
71+
5472
[[simulated_sps.gimlet.components]]
5573
id = "sp3-host-cpu"
5674
device = "sp3-host-cpu"

sp-sim/src/config.rs

+55-5
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,65 @@ use std::path::Path;
1717
use std::path::PathBuf;
1818
use thiserror::Error;
1919

20+
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
21+
#[serde(rename_all = "snake_case")]
22+
pub enum NetworkConfig {
23+
/// Listen address for a fake KSZ8463 port
24+
Simulated { bind_addr: SocketAddrV6 },
25+
26+
Real {
27+
bind_addr: SocketAddrV6,
28+
29+
/// IPv6 multicast address
30+
multicast_addr: Ipv6Addr,
31+
32+
/// IPv6 multicast interface to use.
33+
multicast_interface: String,
34+
},
35+
}
36+
37+
impl slog::KV for NetworkConfig {
38+
fn serialize(
39+
&self,
40+
_record: &slog::Record<'_>,
41+
serializer: &mut dyn slog::Serializer,
42+
) -> slog::Result {
43+
match &self {
44+
NetworkConfig::Simulated { bind_addr } => {
45+
serializer.emit_str("type".into(), "simulated")?;
46+
serializer
47+
.emit_str("bind_addr".into(), &bind_addr.to_string())?;
48+
}
49+
50+
NetworkConfig::Real {
51+
bind_addr,
52+
multicast_addr,
53+
multicast_interface,
54+
} => {
55+
serializer.emit_str("type".into(), "real")?;
56+
serializer
57+
.emit_str("bind_addr".into(), &bind_addr.to_string())?;
58+
serializer.emit_str(
59+
"multicast_addr".into(),
60+
&multicast_addr.to_string(),
61+
)?;
62+
serializer.emit_str(
63+
"multicast_interface".into(),
64+
&multicast_interface,
65+
)?;
66+
}
67+
}
68+
69+
Ok(())
70+
}
71+
}
72+
2073
/// Common configuration for all flavors of SP
2174
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
2275
pub struct SpCommonConfig {
23-
/// IPv6 multicast address to join.
24-
#[serde(skip_serializing_if = "Option::is_none", default)]
25-
pub multicast_addr: Option<Ipv6Addr>,
26-
/// UDP address of the two (fake) KSZ8463 ports
76+
/// Network config for the two (fake) KSZ8463 ports.
2777
#[serde(skip_serializing_if = "Option::is_none", default)]
28-
pub bind_addrs: Option<[SocketAddrV6; 2]>,
78+
pub network_config: Option<[NetworkConfig; 2]>,
2979
/// Fake serial number
3080
pub serial_number: String,
3181
/// 32-byte seed to create a manufacturing root certificate.

sp-sim/src/gimlet.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,10 @@ impl Gimlet {
194194
let (commands, commands_rx) = mpsc::unbounded_channel();
195195
let last_request_handled = Arc::default();
196196

197-
// Weird case - if we don't have any bind addresses, we're only being
197+
// Weird case - if we don't have any network config, we're only being
198198
// created to simulate an RoT, so go ahead and return without actually
199199
// starting a simulated SP.
200-
let Some(bind_addrs) = gimlet.common.bind_addrs else {
200+
let Some(network_config) = &gimlet.common.network_config else {
201201
return Ok(Self {
202202
local_addrs: None,
203203
handler: None,
@@ -210,12 +210,14 @@ impl Gimlet {
210210
};
211211

212212
// bind to our two local "KSZ" ports
213-
assert_eq!(bind_addrs.len(), 2); // gimlet SP always has 2 ports
213+
assert_eq!(network_config.len(), 2); // gimlet SP always has 2 ports
214+
214215
let servers = future::try_join(
215-
UdpServer::new(bind_addrs[0], gimlet.common.multicast_addr, &log),
216-
UdpServer::new(bind_addrs[1], gimlet.common.multicast_addr, &log),
216+
UdpServer::new(&network_config[0], &log),
217+
UdpServer::new(&network_config[1], &log),
217218
)
218219
.await?;
220+
219221
let servers = [servers.0, servers.1];
220222

221223
for component_config in &gimlet.common.components {

0 commit comments

Comments
 (0)