Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
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.

18 changes: 16 additions & 2 deletions gateway-messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ pub mod sp_impl;
mod variable_packet;

use bitflags::bitflags;
use core::{fmt, str};
use serde::{Deserialize, Serialize};
use core::fmt;
use core::str;
use serde::Deserialize;
use serde::Serialize;
use serde_repr::Deserialize_repr;
use serde_repr::Serialize_repr;

pub use hubpack::error::Error as HubpackError;
pub use hubpack::{deserialize, serialize, SerializedSize};
Expand Down Expand Up @@ -41,6 +45,16 @@ pub enum RequestKind {
SerialConsoleWrite(SerialConsole),
}

/// Identifier for one of of an SP's KSZ8463 management-network-facing ports.
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr,
)]
#[repr(u8)]
pub enum SpPort {
One = 1,
Two = 2,
}

// TODO: Not all SPs are capable of crafting all these response kinds, but the
// way we're using hubpack requires everyone to allocate Response::MAX_SIZE. Is
// that okay, or should we break this up more?
Expand Down
66 changes: 48 additions & 18 deletions gateway-messages/src/sp_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,64 @@

//! Behavior implemented by both real and simulated SPs.

use crate::{
version, BulkIgnitionState, IgnitionCommand, IgnitionState, Request,
RequestKind, ResponseError, ResponseKind, SerialConsole, SpComponent,
SpMessage, SpMessageKind, SpState,
};
use crate::version;
use crate::BulkIgnitionState;
use crate::IgnitionCommand;
use crate::IgnitionState;
use crate::Request;
use crate::RequestKind;
use crate::ResponseError;
use crate::ResponseKind;
use crate::SerialConsole;
use crate::SpComponent;
use crate::SpMessage;
use crate::SpMessageKind;
use crate::SpPort;
use crate::SpState;
use hubpack::SerializedSize;
use std::net::SocketAddr;

pub trait SpHandler {
fn ping(&mut self) -> Result<(), ResponseError>;
fn ping(
&mut self,
sender: SocketAddr,
port: SpPort,
) -> Result<(), ResponseError>;

fn ignition_state(
&mut self,
sender: SocketAddr,
port: SpPort,
target: u8,
) -> Result<IgnitionState, ResponseError>;

fn bulk_ignition_state(
&mut self,
sender: SocketAddr,
port: SpPort,
) -> Result<BulkIgnitionState, ResponseError>;

fn ignition_command(
&mut self,
sender: SocketAddr,
port: SpPort,
target: u8,
command: IgnitionCommand,
) -> Result<(), ResponseError>;

fn sp_state(&mut self) -> Result<SpState, ResponseError>;
fn sp_state(
&mut self,
sender: SocketAddr,
port: SpPort,
) -> Result<SpState, ResponseError>;

// TODO Should we return "number of bytes written" here, or is it sufficient
// to say "all or none"? Would be nice for the caller to not have to resend
// UDP chunks; can SP ensure it writes all data locally?
fn serial_console_write(
&mut self,
sender: SocketAddr,
port: SpPort,
packet: SerialConsole,
) -> Result<(), ResponseError>;
}
Expand Down Expand Up @@ -148,12 +174,14 @@ impl Default for SpServer {
impl SpServer {
/// Handler for incoming UDP requests.
///
/// `data` should be a UDP packet that has arrived for the current SP. It
/// will be parsed (into a [`Request`]), the appropriate method will be
/// called on `handler`, and a serialized response will
/// be returned, which the caller should send back to the requester.
/// `data` should be a UDP packet that has arrived from `sender` on `port`.
/// It will be parsed (into a [`Request`]), the appropriate method will be
/// called on `handler`, and a serialized response will be returned, which
/// the caller should send back to the requester.
pub fn dispatch<H: SpHandler>(
&mut self,
sender: SocketAddr,
port: SpPort,
data: &[u8],
handler: &mut H,
) -> Result<&[u8], Error> {
Expand All @@ -174,21 +202,23 @@ impl SpServer {

// call out to handler to provide response
let result = match request.kind {
RequestKind::Ping => handler.ping().map(|()| ResponseKind::Pong),
RequestKind::IgnitionState { target } => {
handler.ignition_state(target).map(ResponseKind::IgnitionState)
RequestKind::Ping => {
handler.ping(sender, port).map(|()| ResponseKind::Pong)
}
RequestKind::IgnitionState { target } => handler
.ignition_state(sender, port, target)
.map(ResponseKind::IgnitionState),
RequestKind::BulkIgnitionState => handler
.bulk_ignition_state()
.bulk_ignition_state(sender, port)
.map(ResponseKind::BulkIgnitionState),
RequestKind::IgnitionCommand { target, command } => handler
.ignition_command(target, command)
.ignition_command(sender, port, target, command)
.map(|()| ResponseKind::IgnitionCommandAck),
RequestKind::SpState => {
handler.sp_state().map(ResponseKind::SpState)
handler.sp_state(sender, port).map(ResponseKind::SpState)
}
RequestKind::SerialConsoleWrite(packet) => handler
.serial_console_write(packet)
.serial_console_write(sender, port, packet)
.map(|()| ResponseKind::SerialConsoleWriteAck),
};

Expand Down
6 changes: 3 additions & 3 deletions gateway/examples/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ id = "8afcb12d-f625-4df9-bdf2-f495c3bbd323"
[known_sps]
switches = [
# first switch is assumed to be the local ignition controller
{ sp = "127.0.0.1:23456", switch_port = "127.0.0.1:33456" },
{ sp = "[::1]:33300", switch_port = "[::1]:33200" },
]
sleds = [
{ sp = "127.0.0.1:23457", switch_port = "127.0.0.1:33457" },
{ sp = "127.0.0.1:23458", switch_port = "127.0.0.1:33458" },
{ sp = "[::1]:33310", switch_port = "[::1]:33201" },
{ sp = "[::1]:33320", switch_port = "[::1]:33202" },
]
power_controllers = [
]
Expand Down
8 changes: 4 additions & 4 deletions gateway/tests/integration_tests/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ pub async fn test_setup_with_config(
.sidecars
.iter()
.map(|simsp| KnownSp {
sp: simsp.local_addr(),
switch_port: "127.0.0.1:0".parse().unwrap(),
sp: simsp.local_addr(0),
switch_port: "[::1]:0".parse().unwrap(),
})
.collect::<Vec<_>>();
let gimlets = simrack
.gimlets
.iter()
.map(|simsp| KnownSp {
sp: simsp.local_addr(),
switch_port: "127.0.0.1:0".parse().unwrap(),
sp: simsp.local_addr(0),
switch_port: "[::1]:0".parse().unwrap(),
})
.collect::<Vec<_>>();
server_config.known_sps = KnownSps {
Expand Down
13 changes: 8 additions & 5 deletions gateway/tests/sp_sim_config.test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,25 @@
# concurrently.
#
[[simulated_sps.sidecar]]
bind_address = "127.0.0.1:0"
multicast_addr = "::1"
bind_addrs = ["[::1]:0", "[::1]:0"]
serial_number = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

[[simulated_sps.gimlet]]
bind_address = "127.0.0.1:0"
multicast_addr = "::1"
bind_addrs = ["[::1]:0", "[::1]:0"]
serial_number = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
[[simulated_sps.gimlet.components]]
name = "sp3"
serial_console = "127.0.0.1:0"
serial_console = "[::1]:0"

[[simulated_sps.gimlet]]
bind_address = "127.0.0.1:0"
multicast_addr = "::1"
bind_addrs = ["[::1]:0", "[::1]:0"]
serial_number = [4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7]
[[simulated_sps.gimlet.components]]
name = "sp3"
serial_console = "127.0.0.1:0"
serial_console = "[::1]:0"

#
# NOTE: for the test suite, the [log] section is ignored; sp-sim logs are rolled
Expand Down
1 change: 1 addition & 0 deletions sp-sim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license = "MPL-2.0"
anyhow = "1.0"
async-trait = "0.1.53"
dropshot = { git = "https://github.com/oxidecomputer/dropshot", branch = "main", features = [ "usdt-probes" ] }
futures = "0.3"
gateway-messages = { path = "../gateway-messages" }
hex = "0.4.3"
omicron-common = { path = "../common" }
Expand Down
13 changes: 8 additions & 5 deletions sp-sim/examples/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
#

[[simulated_sps.sidecar]]
bind_address = "127.0.0.1:23456"
multicast_addr = "ff15:0:1de::0"
bind_addrs = ["[::1]:33300", "[::1]:33301"]
serial_number = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]

[[simulated_sps.gimlet]]
bind_address = "127.0.0.1:23457"
multicast_addr = "ff15:0:1de::1"
bind_addrs = ["[::1]:33310", "[::1]:33311"]
serial_number = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]
[[simulated_sps.gimlet.components]]
name = "sp3"
serial_console = "127.0.0.1:33457"
serial_console = "[::1]:33312"

[[simulated_sps.gimlet]]
bind_address = "127.0.0.1:23458"
multicast_addr = "ff15:0:1de::2"
bind_addrs = ["[::1]:33320", "[::1]:33321"]
serial_number = [4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7]
[[simulated_sps.gimlet.components]]
name = "sp3"
serial_console = "127.0.0.1:33458"
serial_console = "[::1]:33322"

[log]
# Show log messages of this level and more severe
Expand Down
29 changes: 14 additions & 15 deletions sp-sim/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,32 @@

use dropshot::ConfigLogging;
use gateway_messages::SerialNumber;
use serde::{Deserialize, Serialize};
use std::{
net::SocketAddr,
path::{Path, PathBuf},
};
use serde::Deserialize;
use serde::Serialize;
use std::net::Ipv6Addr;
use std::net::SocketAddr;
use std::path::Path;
use std::path::PathBuf;
use thiserror::Error;

/// Configuration of a simulated sidecar SP
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct SidecarConfig {
/// UDP address
pub bind_address: SocketAddr,
/// IPv6 multicast address to join.
pub multicast_addr: Ipv6Addr,
/// UDP address of the two (fake) KSZ8463 ports
pub bind_addrs: [SocketAddr; 2],
/// Fake serial number
pub serial_number: SerialNumber,
}

/// Configuration of a simulated gimlet SP
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct GimletConfig {
/// UDP address
pub bind_address: SocketAddr,
/// IPv6 multicast address to join.
pub multicast_addr: Ipv6Addr,
/// UDP address of the two (fake) KSZ8463 ports
pub bind_addrs: [SocketAddr; 2],
/// Fake serial number
pub serial_number: SerialNumber,
/// Attached components
Expand Down Expand Up @@ -60,12 +65,6 @@ pub struct Config {
pub simulated_sps: SimulatedSps,
/// Server-wide logging configuration.
pub log: ConfigLogging,
// Type of SP to simulate.
// pub sp_type: SpType,
// Components to simulate.
// pub components: SpComponents,
// UDP listen address.
// pub bind_address: SocketAddr,
}

impl Config {
Expand Down
Loading