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
12 changes: 12 additions & 0 deletions Cargo.lock

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

20 changes: 17 additions & 3 deletions gateway-messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct Request {

#[derive(Debug, Clone, SerializedSize, Serialize, Deserialize)]
pub enum RequestKind {
Ping,
Discover,
// TODO do we want to be able to request IgnitionState for all targets in
// one message?
IgnitionState { target: u8 },
Expand All @@ -47,7 +47,15 @@ pub enum RequestKind {

/// Identifier for one of of an SP's KSZ8463 management-network-facing ports.
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr,
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Serialize_repr,
Deserialize_repr,
SerializedSize,
)]
#[repr(u8)]
pub enum SpPort {
Expand All @@ -60,14 +68,20 @@ pub enum SpPort {
// that okay, or should we break this up more?
#[derive(Debug, Clone, SerializedSize, Serialize, Deserialize)]
pub enum ResponseKind {
Pong,
Discover(DiscoverResponse),
IgnitionState(IgnitionState),
BulkIgnitionState(BulkIgnitionState),
IgnitionCommandAck,
SpState(SpState),
SerialConsoleWriteAck,
}

#[derive(Debug, Clone, Copy, SerializedSize, Serialize, Deserialize)]
pub struct DiscoverResponse {
/// Which SP port received the `Discover` request.
pub sp_port: SpPort,
}

// TODO how is this reported? Same/different for components?
pub type SerialNumber = [u8; 16];

Expand Down
9 changes: 5 additions & 4 deletions gateway-messages/src/sp_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use crate::version;
use crate::BulkIgnitionState;
use crate::DiscoverResponse;
use crate::IgnitionCommand;
use crate::IgnitionState;
use crate::Request;
Expand All @@ -22,11 +23,11 @@ use hubpack::SerializedSize;
use std::net::SocketAddr;

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

fn ignition_state(
&mut self,
Expand Down Expand Up @@ -202,8 +203,8 @@ impl SpServer {

// call out to handler to provide response
let result = match request.kind {
RequestKind::Ping => {
handler.ping(sender, port).map(|()| ResponseKind::Pong)
RequestKind::Discover => {
handler.discover(sender, port).map(ResponseKind::Discover)
}
RequestKind::IgnitionState { target } => handler
.ignition_state(sender, port, target)
Expand Down
1 change: 1 addition & 0 deletions gateway-sp-comms/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ringbuffer = "0.8"
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0.30"
tokio-tungstenite = "0.17"
tokio-stream = "0.1.8"
usdt = "0.3.1"
uuid = "0.8"

Expand Down
85 changes: 51 additions & 34 deletions gateway-sp-comms/src/communicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use futures::Future;
use futures::Stream;
use gateway_messages::version;
use gateway_messages::BulkIgnitionState;
use gateway_messages::DiscoverResponse;
use gateway_messages::IgnitionCommand;
use gateway_messages::IgnitionState;
use gateway_messages::Request;
Expand Down Expand Up @@ -113,13 +114,14 @@ impl Communicator {
let request =
RequestKind::IgnitionState { target: port.as_ignition_target() };

self.request_response(
&controller,
request,
Some(timeout),
ResponseKindExt::try_into_ignition_state,
)
.await
Ok(self
.request_response(
&controller,
request,
ResponseKindExt::try_into_ignition_state,
Some(timeout),
)
.await?)
}

/// Ask the local ignition controller for the ignition state of all SPs.
Expand All @@ -134,8 +136,8 @@ impl Communicator {
.request_response(
&controller,
request,
Some(timeout),
ResponseKindExt::try_into_bulk_ignition_state,
Some(timeout),
)
.await?;

Expand Down Expand Up @@ -172,13 +174,14 @@ impl Communicator {
let target = self.id_to_port(target_sp)?.as_ignition_target();
let request = RequestKind::IgnitionCommand { target, command };

self.request_response(
&controller,
request,
Some(timeout),
ResponseKindExt::try_into_ignition_command_ack,
)
.await
Ok(self
.request_response(
&controller,
request,
ResponseKindExt::try_into_ignition_command_ack,
Some(timeout),
)
.await?)
}

/// Set up a websocket connection that forwards data to and from the given
Expand Down Expand Up @@ -298,13 +301,14 @@ impl Communicator {
let sp =
self.switch.sp_socket(port).expect("lost address of attached SP");

self.request_response(
&sp,
RequestKind::SerialConsoleWrite(packet),
Some(timeout),
ResponseKindExt::try_into_serial_console_write_ack,
)
.await
Ok(self
.request_response(
&sp,
RequestKind::SerialConsoleWrite(packet),
ResponseKindExt::try_into_serial_console_write_ack,
Some(timeout),
)
.await?)
}

/// Get the state of a given SP.
Expand Down Expand Up @@ -340,13 +344,14 @@ impl Communicator {
self.switch.sp_socket(port).ok_or(Error::SpAddressUnknown(sp))?;
let request = RequestKind::SpState;

self.request_response(
&sp,
request,
timeout,
ResponseKindExt::try_into_sp_state,
)
.await
Ok(self
.request_response(
&sp,
request,
ResponseKindExt::try_into_sp_state,
timeout,
)
.await?)
}

/// Query all online SPs.
Expand Down Expand Up @@ -393,12 +398,12 @@ impl Communicator {
.collect::<FuturesUnordered<_>>()
}

async fn request_response<F, T>(
pub(crate) async fn request_response<F, T>(
&self,
sp: &SpSocket<'_>,
mut kind: RequestKind,
timeout: Option<Timeout>,
mut map_response_kind: F,
timeout: Option<Timeout>,
) -> Result<T, Error>
where
F: FnMut(ResponseKind) -> Result<T, BadResponseType>,
Expand Down Expand Up @@ -494,9 +499,11 @@ impl Communicator {

// When we send a request we expect a specific kind of response; the boilerplate
// for confirming that is a little noisy, so it lives in this extension trait.
trait ResponseKindExt {
pub(crate) trait ResponseKindExt {
fn name(&self) -> &'static str;

fn try_into_discover(self) -> Result<DiscoverResponse, BadResponseType>;

fn try_into_ignition_state(self) -> Result<IgnitionState, BadResponseType>;

fn try_into_bulk_ignition_state(
Expand All @@ -513,7 +520,7 @@ trait ResponseKindExt {
impl ResponseKindExt for ResponseKind {
fn name(&self) -> &'static str {
match self {
ResponseKind::Pong => response_kind_names::PONG,
ResponseKind::Discover(_) => response_kind_names::DISCOVER,
ResponseKind::IgnitionState(_) => {
response_kind_names::IGNITION_STATE
}
Expand All @@ -530,6 +537,16 @@ impl ResponseKindExt for ResponseKind {
}
}

fn try_into_discover(self) -> Result<DiscoverResponse, BadResponseType> {
match self {
ResponseKind::Discover(discover) => Ok(discover),
other => Err(BadResponseType {
expected: response_kind_names::DISCOVER,
got: other.name(),
}),
}
}

fn try_into_ignition_state(self) -> Result<IgnitionState, BadResponseType> {
match self {
ResponseKind::IgnitionState(state) => Ok(state),
Expand Down Expand Up @@ -584,7 +601,7 @@ impl ResponseKindExt for ResponseKind {
}

mod response_kind_names {
pub(super) const PONG: &str = "pong";
pub(super) const DISCOVER: &str = "discover";
pub(super) const IGNITION_STATE: &str = "ignition_state";
pub(super) const BULK_IGNITION_STATE: &str = "bulk_ignition_state";
pub(super) const IGNITION_COMMAND_ACK: &str = "ignition_command_ack";
Expand Down
8 changes: 8 additions & 0 deletions gateway-sp-comms/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,20 @@ use thiserror::Error;
pub enum StartupError {
#[error("error binding to UDP address {addr}: {err}")]
UdpBind { addr: SocketAddr, err: io::Error },
#[error("invalid configuration file: {}", .reasons.join(", "))]
InvalidConfig { reasons: Vec<String> },
#[error("error communicating with SP: {0}")]
SpCommunicationFailed(#[from] SpCommunicationError),
#[error("location discovery failed: {reason}")]
DiscoveryFailed { reason: String },
}

#[derive(Debug, Error)]
pub enum Error {
#[error("nonexistent SP (type {:?}, slot {})", .0.typ, .0.slot)]
SpDoesNotExist(SpIdentifier),
#[error("unknown socket address for local ignition controller")]
LocalIgnitionControllerAddressUnknown,
#[error(
"unknown socket address for SP (type {:?}, slot {})",
.0.typ,
Expand Down
14 changes: 12 additions & 2 deletions gateway-sp-comms/src/management_switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
//! See RFD 250 for details.
//!

#[allow(dead_code)] // we don't use this yet, but will shortly
mod location_map;

use crate::error::StartupError;
use futures::stream::FuturesUnordered;
use futures::StreamExt;
Expand Down Expand Up @@ -48,13 +51,20 @@ pub struct KnownSps {
pub power_controllers: Vec<KnownSp>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct SpIdentifier {
pub typ: SpType,
pub slot: usize,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
impl SpIdentifier {
pub fn new(typ: SpType, slot: usize) -> Self {
Self { typ, slot }
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SpType {
Switch,
Sled,
Expand Down
Loading