From 323132041ec5d0e34b6687a49b1cfe45cc3c26a2 Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Thu, 12 Dec 2024 18:21:53 -0800 Subject: [PATCH 01/11] mctp syscall driver draft --- runtime/capsules/src/mctp/base_protocol.rs | 6 +- runtime/capsules/src/mctp/common.rs | 7 + runtime/capsules/src/mctp/driver.rs | 301 +++++++++++++++++++++ runtime/capsules/src/mctp/mod.rs | 4 + runtime/capsules/src/mctp/mux.rs | 169 ++++++------ runtime/capsules/src/mctp/recv.rs | 190 +++++++++++++ runtime/capsules/src/mctp/send.rs | 56 ++++ 7 files changed, 648 insertions(+), 85 deletions(-) create mode 100644 runtime/capsules/src/mctp/common.rs create mode 100644 runtime/capsules/src/mctp/driver.rs create mode 100644 runtime/capsules/src/mctp/recv.rs create mode 100644 runtime/capsules/src/mctp/send.rs diff --git a/runtime/capsules/src/mctp/base_protocol.rs b/runtime/capsules/src/mctp/base_protocol.rs index 2ac0e8e..6f640e4 100644 --- a/runtime/capsules/src/mctp/base_protocol.rs +++ b/runtime/capsules/src/mctp/base_protocol.rs @@ -58,9 +58,13 @@ impl MCTPHeader<[u8; MCTP_HDR_SIZE]> { self.set_tag_owner(tag_owner); self.set_msg_tag(msg_tag); } + + pub fn next_pkt_seq(&self) -> u8 { + (self.pkt_seq() + 1) % 4 + } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum MessageType { MCTPControl, PLDM, diff --git a/runtime/capsules/src/mctp/common.rs b/runtime/capsules/src/mctp/common.rs new file mode 100644 index 0000000..dc46a47 --- /dev/null +++ b/runtime/capsules/src/mctp/common.rs @@ -0,0 +1,7 @@ +// Licensed under the Apache-2.0 license + +pub const MCTP_TAG_OWNER: u8 = 0x08; +pub const MCTP_TAG_MASK: u8 = 0x07; + +pub const MCTP_PROTOCOL_VERSION_1: u8 = 0x01; +pub const MCTP_PROTOCOL_VERSION_MASK: u8 = 0x0F; diff --git a/runtime/capsules/src/mctp/driver.rs b/runtime/capsules/src/mctp/driver.rs new file mode 100644 index 0000000..f718692 --- /dev/null +++ b/runtime/capsules/src/mctp/driver.rs @@ -0,0 +1,301 @@ +// Licensed under the Apache-2.0 license + +use crate::mctp::recv::MCTPRxClient; +use crate::mctp::send::{MCTPSender, MCTPTxClient}; + +use crate::mctp::common::*; + +use core::cell::Cell; + +use kernel::debug; +use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; +use kernel::processbuffer::WriteableProcessBuffer; +use kernel::syscall::{CommandReturn, SyscallDriver}; +use kernel::utilities::cells::MapCell; +use kernel::utilities::leasable_buffer::SubSliceMut; +use kernel::{ErrorCode, ProcessId}; + +pub const MAX_MESSAGE_TYPES: usize = 2; + +pub const SPDM_MAX_MESSAGE_SIZE: usize = 4098; +pub const PLDM_MAX_MESSAGE_SIZE: usize = 4098; +pub const VENDOR_DEFINED_PCI_MAX_MESSAGE_SIZE: usize = 4098; + +pub const MCTP_SPDM_DRIVER_NUM: usize = 0xA0000; +pub const MCTP_PLDM_DRIVER_NUM: usize = 0xA0001; +pub const MCTP_VENDOR_DEFINED_PCI_DRIVER_NUM: usize = 0xA0002; + +/// IDs for subscribe calls +mod upcall { + /// Callback for when the message is received + pub const MESSAGE_RECEIVED: usize = 0; + + /// Callback for when the message is transmitted. + pub const MESSAGE_TRANSMITTED: usize = 1; + + /// Number of upcalls + pub const COUNT: u8 = 2; +} + +/// IDs for read-only allow buffers +mod ro_allow { + /// Buffer for the message to be transmitted + pub const MESSAGE_WRITE: usize = 0; + + /// Number of read-only allow buffers + pub const COUNT: u8 = 1; +} + +/// IDs for read-write allow buffers +mod rw_allow { + /// Buffer for the message to be received + pub const MESSAGE_READ: usize = 0; + + /// Number of read-write allow buffers + pub const COUNT: u8 = 1; +} + +enum OpType { + SendReq, + SendResp, + ReceiveReq, + ReceiveResp, + Idle, +} + +struct OpContext { + msg_tag: u8, + peer_eid: u8, + msg_type: u8, + op_type: OpType, +} + +impl OpContext { + fn is_match(&self, msg_tag: u8, peer_eid: u8, msg_type: u8) -> bool { + if self.msg_type != msg_type { + return false; + } + match self.op_type { + OpType::ReceiveReq => { + if msg_tag & MCTP_TAG_OWNER != 0 { + return true; + } + } + OpType::ReceiveResp => { + if self.msg_tag & MCTP_TAG_MASK == msg_tag && self.peer_eid == peer_eid { + return true; + } + } + _ => {} + } + false + } +} + +#[derive(Default)] +pub struct App { + pending_op_ctx: Option, + pending_tx: Option, +} + +pub struct MCTPDriver<'a> { + sender: &'a dyn MCTPSender, + apps: Grant< + App, + UpcallCount<{ upcall::COUNT }>, + AllowRoCount<{ ro_allow::COUNT }>, + AllowRwCount<{ rw_allow::COUNT }>, + >, + app_id: Cell>, + msg_types: [u8; MAX_MESSAGE_TYPES], + max_msg_size: usize, + kernel_msg_buf: MapCell>, +} + +impl<'a> MCTPDriver<'a> { + pub fn new( + sender: &'a dyn MCTPSender, + grant: Grant< + App, + UpcallCount<{ upcall::COUNT }>, + AllowRoCount<{ ro_allow::COUNT }>, + AllowRwCount<{ rw_allow::COUNT }>, + >, + msg_types: [u8; MAX_MESSAGE_TYPES], + max_msg_size: usize, + msg_buf: SubSliceMut<'static, u8>, + ) -> MCTPDriver<'a> { + MCTPDriver { + sender, + apps: grant, + app_id: Cell::new(None), + msg_types, + max_msg_size, + kernel_msg_buf: MapCell::new(msg_buf), + } + } + + fn supported_msg_type(&self, msg_type: u8) -> bool { + for i in 0..MAX_MESSAGE_TYPES { + if msg_type == self.msg_types[i] { + return true; + } + } + false + } +} + +impl<'a> SyscallDriver for MCTPDriver<'a> { + fn command( + &self, + command_num: usize, + arg1: usize, + arg2: usize, + process_id: ProcessId, + ) -> CommandReturn { + + // lower 8 bits of arg2 is always msg_type + let msg_type = arg2 as u8; + if !self.supported_msg_type(msg_type) { + return CommandReturn::failure(ErrorCode::INVAL); + } + + match command_num { + 0 => CommandReturn::success(), + // Receive Request Message + // arg1: peer_eid + // arg2: msg_type + 1 => self + .apps + .enter(process_id, |app, _| { + app.pending_op_ctx = Some(OpContext { + msg_tag: MCTP_TAG_OWNER, + peer_eid: arg1 as u8, + msg_type: msg_type, + op_type: OpType::ReceiveReq, + }); + CommandReturn::success() + }) + .unwrap_or_else(|err| CommandReturn::failure(err.into())), + // Receive Response Message + // arg1: peer_eid + // arg2: msg_tag << 8 | msg_type + 2 => self + .apps + .enter(process_id, |app, _| { + let peer_eid = arg1 as u8; + let msg_tag = ((arg2 >> 8) & 0xFF) as u8; + + app.pending_op_ctx = Some(OpContext { + msg_tag, + peer_eid, + msg_type, + op_type: OpType::ReceiveResp, + }); + CommandReturn::success() + }) + .unwrap_or_else(|err| CommandReturn::failure(err.into())), + // Send Request Message + // arg1: dest_eid + // arg2: msg_type + 3 => { + let result = self.apps.enter(process_id, |app, kernel_data| { + let dest_eid = arg1 as u8; + + if app.pending_tx.is_some() { + return Err(ErrorCode::BUSY); + } + + // copy the app buffer into kernel buffer + kernel_data + .get_readonly_processbuffer(ro_allow::MESSAGE_WRITE) + .and_then(|write| { + write.enter(|wmsg_payload| { + let mut msg_buf = self.kernel_msg_buf.take(); + match msg_buf { + Some(msg_buf) => { + if wmsg_payload.len() > msg_buf.len() { + return Err(ErrorCode::SIZE); + } + msg_buf[..wmsg_payload.len()].copy_from_slice(wmsg_payload); + self.kernel_msg_buf.replace(msg_buf); + Ok(()) + } + None => Err(ErrorCode::NOMEM), + } + }) + }) + .unwrap_or_else(|err| Err(err.into()))?; + + + + + + + }).unwrap_or_else(|err| Err(err.into())); + match result { + Ok(_) => { + debug!("MCTPDriver::command: 3. Send Request Message"); + CommandReturn::success() + } + Err(e) => CommandReturn::failure(e), + } + 4 => { + debug!("MCTPDriver::command: 4. TODO Send Response Message"); + CommandReturn::success() + } + 5 => CommandReturn::success_u32(self.max_msg_size as u32), + _ => CommandReturn::failure(ErrorCode::NOSUPPORT), + } + } + + fn allocate_grant(&self, process_id: ProcessId) -> Result<(), kernel::process::Error> { + self.apps.enter(process_id, |_, _| {}) + } +} + +impl<'a> MCTPTxClient for MCTPDriver<'a> { + fn send_done( + &self, + msg_tag: Option, + result: Result<(), ErrorCode>, + msg_payload: SubSliceMut<'static, u8>, + ) { + debug!("MCTPDriver::send_done: {:?}", result); + } +} + +impl<'a> MCTPRxClient for MCTPDriver<'a> { + fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { + self.apps.each(|_, app, kernel_data| { + if let Some(op_ctx) = app.pending_op_ctx.as_mut() { + if op_ctx.is_match(msg_tag, src_eid, msg_type) { + let res = kernel_data + .get_readwrite_processbuffer(rw_allow::MESSAGE_READ) + .and_then(|read| { + read.mut_enter(|rmsg_payload| { + if rmsg_payload.len() < msg_len { + Err(ErrorCode::SIZE) + } else { + rmsg_payload[..msg_len].copy_from_slice(msg_payload); + Ok(()) + } + }) + }) + .unwrap_or(Ok(())); + + if res.is_ok() { + app.pending_op_ctx = None; + let msg_info = msg_type << 8 | msg_tag; + kernel_data + .schedule_upcall( + upcall::MESSAGE_RECEIVED, + (msg_len, src_eid as usize, msg_info as usize), + ) + .ok(); + } + } + } + }); + } +} diff --git a/runtime/capsules/src/mctp/mod.rs b/runtime/capsules/src/mctp/mod.rs index 257801e..86b3a4e 100644 --- a/runtime/capsules/src/mctp/mod.rs +++ b/runtime/capsules/src/mctp/mod.rs @@ -1,6 +1,10 @@ // Licensed under the Apache-2.0 license pub mod base_protocol; +pub mod common; pub mod control_msg; +pub mod driver; pub mod mux; +pub mod recv; +pub mod send; pub mod transport_binding; diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index c960b20..da66e3b 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -2,102 +2,23 @@ use crate::mctp::base_protocol::{MCTPHeader, MessageType, MCTP_HDR_SIZE}; use crate::mctp::control_msg::{MCTPCtrlCmd, MCTPCtrlMsgHdr, MCTP_CTRL_MSG_HEADER_LEN}; +use crate::mctp::recv::MCTPRxState; +use crate::mctp::send::MCTPTxState; use crate::mctp::transport_binding::{MCTPTransportBinding, TransportRxClient, TransportTxClient}; +use capsules_extra::net::sixlowpan::sixlowpan_compression::Context; use core::fmt::Write; use romtime::println; use core::cell::Cell; -use kernel::collections::list::{List, ListLink, ListNode}; -use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; +use kernel::collections::list::List; +use kernel::utilities::cells::{MapCell, TakeCell}; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; use zerocopy::{FromBytes, IntoBytes}; -/// The trait that provides an interface to send the MCTP messages to MCTP kernel stack. -pub trait MCTPSender { - /// Sets the client for the `MCTPSender` instance. - fn set_client(&self, client: &dyn MCTPTxClient); - - /// Sends the message to the MCTP kernel stack. - fn send_msg(&self, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>); -} - -/// This trait is implemented by client to get notified after message is sent. -pub trait MCTPTxClient { - fn send_done( - &self, - msg_tag: Option, - result: Result<(), ErrorCode>, - msg_payload: SubSliceMut<'static, u8>, - ); -} - -/// This trait is implemented to get notified of the messages received -/// on corresponding message_type. -pub trait MCTPRxClient { - fn receive(&self, dst_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8]); -} - -/// Send state for MCTP -#[allow(dead_code)] -pub struct MCTPTxState<'a, M: MCTPTransportBinding<'a>> { - mctp_mux_sender: &'a MuxMCTPDriver<'a, M>, - /// Destination EID - dest_eid: Cell, - /// Message type - msg_type: Cell, - /// msg_tag for the message being packetized - msg_tag: Cell, - /// Current packet sequence - pkt_seq: Cell, - /// Offset into the message buffer - offset: Cell, - /// Client to invoke when send done. This is set to the corresponding Virtual MCTP driver - client: OptionalCell<&'a dyn MCTPTxClient>, - /// next node in the list - next: ListLink<'a, MCTPTxState<'a, M>>, - /// The message buffer is set by the virtual MCTP driver when it issues the Tx request. - msg_payload: MapCell>, -} - -impl<'a, M: MCTPTransportBinding<'a>> ListNode<'a, MCTPTxState<'a, M>> for MCTPTxState<'a, M> { - fn next(&'a self) -> &'a ListLink<'a, MCTPTxState<'a, M>> { - &self.next - } -} - -/// Receive state -#[allow(dead_code)] -pub struct MCTPRxState<'a> { - /// Source EID - source_eid: Cell, - /// message type - msg_type: Cell, - /// msg_tag for the message being assembled - msg_tag: Cell, - /// Current packet sequence - pkt_seq: Cell, - /// Offset into the message buffer - offset: Cell, - /// Start packet len - start_pkt_len: Cell, - /// Client (implements the MCTPRxClient trait) - client: OptionalCell<&'a dyn MCTPRxClient>, - /// Message buffer - msg_payload: MapCell>, - /// next MCTPRxState node - next: ListLink<'a, MCTPRxState<'a>>, -} - -impl<'a> ListNode<'a, MCTPRxState<'a>> for MCTPRxState<'a> { - fn next(&'a self) -> &'a ListLink<'a, MCTPRxState<'a>> { - &self.next - } -} - /// MUX struct that manages multiple MCTP driver users (clients). /// /// This struct implements a FIFO queue for the @@ -338,6 +259,74 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { }) } + // fn receive_packet( + // &self, + // mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, + // msg_type: MessageType, + // pkt_payload: &[u8], + // ) -> Result<(), ErrorCode> { + // let msg_type_val = msg_type as u8; + // let rx_state = self + // .receiver_list + // .iter() + // .find(|rx_state| rx_state.receive_pending(msg_type_val)); + + // if let Some(rx_state) = rx_state { + + // if mctp_hdr. + // rx_state.is_m(mctp_hdr, pkt_payload); + // } else { + // println!("MuxMCTPDriver: No matching receive request found. Dropping packet."); + // } + // Ok(()) + + // } + + fn process_first_packet( + &self, + mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, + msg_type: MessageType, + pkt_payload: &[u8], + ) { + let rx_state = self + .receiver_list + .iter() + .find(|rx_state| rx_state.is_receive_expected(msg_type)); + + if let Some(rx_state) = rx_state { + rx_state.start_receive(mctp_hdr, msg_type, pkt_payload); + } else { + println!("MuxMCTPDriver: No matching receive request found. Dropping packet."); + } + } + + fn process_packet(&self, mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, pkt_payload: &[u8]) { + if self.local_eid != mctp_hdr.dest_eid().into() { + println!("MuxMCTPDriver: Packet not for this Endpoint. Dropping packet."); + return; + } + + if mctp_hdr.eom() != 1 && pkt_payload.len() < 64 { + println!("MuxMCTPDriver: Received first or middle packet with less than 64 bytes. Dropping packet."); + return; + } + + let rx_state = self + .receiver_list + .iter() + .find(|rx_state| rx_state.is_next_packet(&mctp_hdr, pkt_payload.len())); + + match rx_state { + Some(rx_state) => { + rx_state.receive_next(mctp_hdr, pkt_payload); + } + None => { + println!("MuxMCTPDriver: No matching receive request found. Dropping packet."); + return; + } + } + } + fn get_total_hdr_size(&self) -> usize { MCTP_HDR_SIZE + self.mctp_device.get_hdr_size() } @@ -371,10 +360,22 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> println!("MuxMCTPDriver: Invalid MCTP Control message. Dropping packet."); } } + MessageType::PLDM + | MessageType::SPDM + | MessageType::SSPDM + | MessageType::VendorDefinedPCI => { + self.process_first_packet( + mctp_header, + msg_type, + &rx_buffer[payload_offset..len], + ); + } _ => { println!("MuxMCTPDriver: Unsupported message type. Dropping packet."); } } + } else { + self.process_packet(mctp_header, &rx_buffer[payload_offset..len]); } self.rx_pkt_buffer.replace(rx_buffer); } diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs new file mode 100644 index 0000000..df6bb9b --- /dev/null +++ b/runtime/capsules/src/mctp/recv.rs @@ -0,0 +1,190 @@ +use crate::mctp::base_protocol::MCTPHeader; + +use core::fmt::Write; +use romtime::println; + +use core::cell::Cell; + +use kernel::collections::list::{ListLink, ListNode}; +use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; + +use super::base_protocol::{MessageType, MCTP_HDR_SIZE}; +use super::common::{MCTP_TAG_MASK, MCTP_TAG_OWNER}; +use super::driver::MAX_MESSAGE_TYPES; + +/// This trait is implemented to get notified of the messages received +/// on corresponding message_type. +pub trait MCTPRxClient { + fn receive(&self, dst_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize); +} + +/// Receive state +#[allow(dead_code)] +pub struct MCTPRxState<'a> { + /// Message assembly context + msg_terminus: MapCell, + msg_types: Cell<[u8; MAX_MESSAGE_TYPES]>, + // // /// Source EID + // // source_eid: Cell, + // /// message type + // msg_type: Cell, + // /// msg_tag for the message being assembled + // msg_tag: Cell, + /// Current packet sequence + // pkt_seq: Cell, + /// msg_size in the message buffer + msg_size: Cell, + /// Client (implements the MCTPRxClient trait) + client: OptionalCell<&'a dyn MCTPRxClient>, + /// Message buffer + msg_payload: TakeCell<'static, [u8]>, + /// next MCTPRxState node + next: ListLink<'a, MCTPRxState<'a>>, +} + +impl<'a> ListNode<'a, MCTPRxState<'a>> for MCTPRxState<'a> { + fn next(&'a self) -> &'a ListLink<'a, MCTPRxState<'a>> { + &self.next + } +} + +struct MsgTerminus { + msg_type: u8, + msg_tag: u8, + source_eid: u8, + tag_owner: u8, + start_payload_len: usize, + pkt_seq: u8, +} + +impl<'a> MCTPRxState<'a> { + pub fn new( + rx_msg_buf: &'static mut [u8], + message_types: [u8; MAX_MESSAGE_TYPES], + ) -> MCTPRxState<'static> { + MCTPRxState { + msg_terminus: MapCell::empty(), + msg_types: Cell::new(message_types), + msg_size: Cell::new(0), + client: OptionalCell::empty(), + msg_payload: TakeCell::new(rx_msg_buf), + next: ListLink::empty(), + } + } + + pub fn set_client(&self, client: &'a dyn MCTPRxClient) { + self.client.set(client); + } + + pub fn is_receive_expected(&self, msg_type: MessageType) -> bool { + let msg_types = self.msg_types.get(); + for i in 0..MAX_MESSAGE_TYPES { + if msg_type as u8 == msg_types[i] { + return true; + } + } + false + } + + pub fn is_next_packet( + &self, + mctp_hdr: &MCTPHeader<[u8; MCTP_HDR_SIZE]>, + pkt_payload_len: usize, + ) -> bool { + self.msg_terminus + .map(|msg_terminus| { + msg_terminus.tag_owner == mctp_hdr.tag_owner() + && msg_terminus.msg_tag == mctp_hdr.msg_tag() + && msg_terminus.source_eid == mctp_hdr.src_eid() + && msg_terminus.pkt_seq == mctp_hdr.pkt_seq() + && (mctp_hdr.som() == 0 + && mctp_hdr.eom() == 0 + && msg_terminus.start_payload_len == pkt_payload_len) // middle packet + }) + .unwrap_or(false) + } + + pub fn receive_next(&self, mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, pkt_payload: &[u8]) { + if let Some(mut msg_terminus) = self.msg_terminus.take() { + let offset = self.msg_size.get(); + let end_offset = offset + pkt_payload.len(); + if end_offset > self.msg_payload.map_or(0, |msg_payload| msg_payload.len()) { + println!("MCTPMuxDriver - Received packet with payload length greater than buffer size. Dropping packet."); + self.msg_size.set(0); + return; + } + + self.msg_payload.map(|msg_payload| { + msg_payload[offset..end_offset].copy_from_slice(pkt_payload); + self.msg_size.set(end_offset); + }); + msg_terminus.pkt_seq = mctp_hdr.next_pkt_seq(); + self.msg_terminus.replace(msg_terminus); + } + + if mctp_hdr.eom() == 1 { + self.end_receive(); + } + } + + pub fn end_receive(&self) { + if let Some(msg_terminus) = self.msg_terminus.take() { + let msg_tag = if msg_terminus.tag_owner == 1 { + msg_terminus.msg_tag & MCTP_TAG_MASK | MCTP_TAG_OWNER + } else { + msg_terminus.msg_tag + }; + self.client.map(|client| { + self.msg_payload.map(|msg_payload| { + client.receive( + msg_terminus.source_eid, + msg_terminus.msg_type, + msg_tag, + msg_payload, + self.msg_size.get(), + ); + }); + }); + } + } + + pub fn start_receive( + &self, + mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, + msg_type: MessageType, + pkt_payload: &[u8], + ) { + if mctp_hdr.som() != 1 { + println!("MCTPMuxDriver - Received first packet without SOM. Dropping packet."); + return; + } + + if pkt_payload.len() == 0 { + println!("MCTPMuxDriver - Received packet with no payload. Dropping packet."); + return; + } + + let pkt_payload_len = pkt_payload.len(); + + let msg_terminus = MsgTerminus { + msg_type: msg_type as u8, + msg_tag: mctp_hdr.msg_tag(), + source_eid: mctp_hdr.src_eid(), + tag_owner: mctp_hdr.tag_owner(), + start_payload_len: pkt_payload_len, + pkt_seq: mctp_hdr.next_pkt_seq(), + }; + + self.msg_terminus.replace(msg_terminus); + + self.msg_payload.take().map(|msg_payload| { + msg_payload[..pkt_payload.len()].copy_from_slice(pkt_payload); + self.msg_payload.replace(msg_payload); + }); + self.msg_size.set(pkt_payload_len); + + if mctp_hdr.eom() == 1 { + self.end_receive(); + } + } +} diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs new file mode 100644 index 0000000..5bd3ca5 --- /dev/null +++ b/runtime/capsules/src/mctp/send.rs @@ -0,0 +1,56 @@ +use crate::mctp::mux::MuxMCTPDriver; +use crate::mctp::transport_binding::MCTPTransportBinding; + +use core::cell::Cell; + +use kernel::collections::list::{ListLink, ListNode}; +use kernel::utilities::cells::{MapCell, OptionalCell}; +use kernel::utilities::leasable_buffer::SubSliceMut; +use kernel::ErrorCode; + +/// The trait that provides an interface to send the MCTP messages to MCTP kernel stack. +pub trait MCTPSender { + /// Sets the client for the `MCTPSender` instance. + fn set_client(&self, client: &dyn MCTPTxClient); + + /// Sends the message to the MCTP kernel stack. + fn send_msg(&self, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>); +} + +/// This trait is implemented by client to get notified after message is sent. +pub trait MCTPTxClient { + fn send_done( + &self, + msg_tag: Option, + result: Result<(), ErrorCode>, + msg_payload: SubSliceMut<'static, u8>, + ); +} + +/// Send state for MCTP +#[allow(dead_code)] +pub struct MCTPTxState<'a, M: MCTPTransportBinding<'a>> { + mctp_mux_sender: &'a MuxMCTPDriver<'a, M>, + /// Destination EID + dest_eid: Cell, + /// Message type + msg_type: Cell, + /// msg_tag for the message being packetized + msg_tag: Cell, + /// Current packet sequence + pkt_seq: Cell, + /// Offset into the message buffer + offset: Cell, + /// Client to invoke when send done. This is set to the corresponding Virtual MCTP driver + client: OptionalCell<&'a dyn MCTPTxClient>, + /// next node in the list + next: ListLink<'a, MCTPTxState<'a, M>>, + /// The message buffer is set by the virtual MCTP driver when it issues the Tx request. + msg_payload: MapCell>, +} + +impl<'a, M: MCTPTransportBinding<'a>> ListNode<'a, MCTPTxState<'a, M>> for MCTPTxState<'a, M> { + fn next(&'a self) -> &'a ListLink<'a, MCTPTxState<'a, M>> { + &self.next + } +} From 2fc71d7fea579032387680b51062f627c7c0ce8d Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Fri, 13 Dec 2024 16:25:12 -0800 Subject: [PATCH 02/11] add tx and rx message handling --- docs/src/mctp.md | 2 +- runtime/capsules/src/mctp/driver.rs | 144 ++++++++++++++++++---------- runtime/capsules/src/mctp/mux.rs | 79 ++++++++------- runtime/capsules/src/mctp/recv.rs | 35 ++++--- runtime/capsules/src/mctp/send.rs | 116 +++++++++++++++++++++- 5 files changed, 275 insertions(+), 101 deletions(-) diff --git a/docs/src/mctp.md b/docs/src/mctp.md index d6914ef..7a58009 100644 --- a/docs/src/mctp.md +++ b/docs/src/mctp.md @@ -306,7 +306,7 @@ pub trait MCTPSender { fn set_client(&self, client: &dyn MCTPTxClient); /// Sends the message to the MCTP kernel stack. - fn send_msg(&self, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>); + fn send_msg(&self, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>) -> Result<(), SubSliceMut<'static, u8>>; } /// This is the trait implemented by VirtualMCTPDriver instance to get notified after diff --git a/runtime/capsules/src/mctp/driver.rs b/runtime/capsules/src/mctp/driver.rs index f718692..b0147c9 100644 --- a/runtime/capsules/src/mctp/driver.rs +++ b/runtime/capsules/src/mctp/driver.rs @@ -6,10 +6,12 @@ use crate::mctp::send::{MCTPSender, MCTPTxClient}; use crate::mctp::common::*; use core::cell::Cell; +use core::fmt::Write; +use romtime::println; use kernel::debug; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; -use kernel::processbuffer::WriteableProcessBuffer; +use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer}; use kernel::syscall::{CommandReturn, SyscallDriver}; use kernel::utilities::cells::MapCell; use kernel::utilities::leasable_buffer::SubSliceMut; @@ -99,14 +101,14 @@ pub struct App { } pub struct MCTPDriver<'a> { - sender: &'a dyn MCTPSender, + sender: &'a dyn MCTPSender<'a>, apps: Grant< App, UpcallCount<{ upcall::COUNT }>, AllowRoCount<{ ro_allow::COUNT }>, AllowRwCount<{ rw_allow::COUNT }>, >, - app_id: Cell>, + current_app: Cell>, msg_types: [u8; MAX_MESSAGE_TYPES], max_msg_size: usize, kernel_msg_buf: MapCell>, @@ -114,7 +116,7 @@ pub struct MCTPDriver<'a> { impl<'a> MCTPDriver<'a> { pub fn new( - sender: &'a dyn MCTPSender, + sender: &'a dyn MCTPSender<'a>, grant: Grant< App, UpcallCount<{ upcall::COUNT }>, @@ -128,7 +130,7 @@ impl<'a> MCTPDriver<'a> { MCTPDriver { sender, apps: grant, - app_id: Cell::new(None), + current_app: Cell::new(None), msg_types, max_msg_size, kernel_msg_buf: MapCell::new(msg_buf), @@ -153,7 +155,6 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { arg2: usize, process_id: ProcessId, ) -> CommandReturn { - // lower 8 bits of arg2 is always msg_type let msg_type = arg2 as u8; if !self.supported_msg_type(msg_type) { @@ -171,7 +172,7 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { app.pending_op_ctx = Some(OpContext { msg_tag: MCTP_TAG_OWNER, peer_eid: arg1 as u8, - msg_type: msg_type, + msg_type, op_type: OpType::ReceiveReq, }); CommandReturn::success() @@ -199,47 +200,70 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { // arg1: dest_eid // arg2: msg_type 3 => { - let result = self.apps.enter(process_id, |app, kernel_data| { - let dest_eid = arg1 as u8; - - if app.pending_tx.is_some() { - return Err(ErrorCode::BUSY); - } - - // copy the app buffer into kernel buffer - kernel_data - .get_readonly_processbuffer(ro_allow::MESSAGE_WRITE) - .and_then(|write| { - write.enter(|wmsg_payload| { - let mut msg_buf = self.kernel_msg_buf.take(); - match msg_buf { - Some(msg_buf) => { - if wmsg_payload.len() > msg_buf.len() { - return Err(ErrorCode::SIZE); - } - msg_buf[..wmsg_payload.len()].copy_from_slice(wmsg_payload); - self.kernel_msg_buf.replace(msg_buf); - Ok(()) - } - None => Err(ErrorCode::NOMEM), - } + let result = self + .apps + .enter(process_id, |app, kernel_data| { + let dest_eid = arg1 as u8; + if app.pending_tx.is_some() { + return Err(ErrorCode::BUSY); + } + + let res = kernel_data + .get_readonly_processbuffer(ro_allow::MESSAGE_WRITE) + .and_then(|write| { + write.enter(|wpayload| { + self.kernel_msg_buf.take().map_or( + Err(ErrorCode::NOMEM), + |mut kernel_msg_buf| { + if wpayload.len() > kernel_msg_buf.len() { + return Err(ErrorCode::SIZE); + } + wpayload.copy_to_slice( + &mut kernel_msg_buf[..wpayload.len()], + ); + kernel_msg_buf.slice(0..wpayload.len()); + + match self.sender.send_msg( + dest_eid, + MCTP_TAG_OWNER, + kernel_msg_buf, + ) { + Ok(_) => { + println!("MCTPDriver: send_msg success"); + app.pending_tx = Some(OpContext { + msg_tag: MCTP_TAG_OWNER, + peer_eid: dest_eid, + msg_type, + op_type: OpType::SendReq, + }); + self.current_app.set(Some(process_id)); + Ok(()) + } + Err(mut buf) => { + println!("MCTPDriver: send_msg failed"); + buf.reset(); + self.kernel_msg_buf.replace(buf); + Err(ErrorCode::FAIL) + } + } + }, + ) + }) }) - }) - .unwrap_or_else(|err| Err(err.into()))?; - - - - - + .unwrap_or(Err(ErrorCode::FAIL)); + match res { + Ok(()) => Ok(()), + Err(e) => Err(e), + } + // Ok(()) + }) + .unwrap_or_else(|err| Err(err.into())); - }).unwrap_or_else(|err| Err(err.into())); match result { - Ok(_) => { - debug!("MCTPDriver::command: 3. Send Request Message"); - CommandReturn::success() - } + Ok(()) => CommandReturn::success(), Err(e) => CommandReturn::failure(e), } + } 4 => { debug!("MCTPDriver::command: 4. TODO Send Response Message"); CommandReturn::success() @@ -257,11 +281,35 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { impl<'a> MCTPTxClient for MCTPDriver<'a> { fn send_done( &self, - msg_tag: Option, + dest_eid: u8, + msg_type: u8, + msg_tag: u8, result: Result<(), ErrorCode>, - msg_payload: SubSliceMut<'static, u8>, + mut msg_payload: SubSliceMut<'static, u8>, ) { - debug!("MCTPDriver::send_done: {:?}", result); + msg_payload.reset(); + self.kernel_msg_buf.replace(msg_payload); + if let Some(process_id) = self.current_app.get() { + _ = self.apps.enter(process_id, |app, up_calls| { + if let Some(op_ctx) = app.pending_tx.as_mut() { + if op_ctx.is_match(msg_tag, dest_eid, msg_type) { + app.pending_tx = None; + let msg_info = (msg_type as usize) << 8 | (msg_tag as usize); + up_calls + .schedule_upcall( + upcall::MESSAGE_TRANSMITTED, + ( + kernel::errorcode::into_statuscode(result), + dest_eid as usize, + msg_info, + ), + ) + .ok(); + } + } + }); + } + self.current_app.set(None); } } @@ -286,11 +334,11 @@ impl<'a> MCTPRxClient for MCTPDriver<'a> { if res.is_ok() { app.pending_op_ctx = None; - let msg_info = msg_type << 8 | msg_tag; + let msg_info = (msg_type as usize) << 8 | (msg_tag as usize); kernel_data .schedule_upcall( upcall::MESSAGE_RECEIVED, - (msg_len, src_eid as usize, msg_info as usize), + (msg_len, src_eid as usize, msg_info), ) .ok(); } diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index da66e3b..e22ed25 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -6,14 +6,13 @@ use crate::mctp::recv::MCTPRxState; use crate::mctp::send::MCTPTxState; use crate::mctp::transport_binding::{MCTPTransportBinding, TransportRxClient, TransportTxClient}; -use capsules_extra::net::sixlowpan::sixlowpan_compression::Context; use core::fmt::Write; use romtime::println; use core::cell::Cell; use kernel::collections::list::List; -use kernel::utilities::cells::{MapCell, TakeCell}; +use kernel::utilities::cells::TakeCell; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; @@ -60,7 +59,13 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { } pub fn add_sender(&self, sender: &'a MCTPTxState<'a, M>) { + let list_empty = self.sender_list.head().is_none(); + self.sender_list.push_tail(sender); + + if list_empty { + self.send_next_packet(sender); + } } pub fn add_receiver(&self, receiver: &'a MCTPRxState<'a>) { @@ -185,9 +190,9 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { mctp_ctrl_msg_hdr.cmd(), ); - let mctp_hdr_offset = self.get_total_hdr_size() - MCTP_HDR_SIZE; - let mctp_ctrl_msg_hdr_offset = mctp_hdr_offset + MCTP_HDR_SIZE; - let msg_payload_offset = mctp_ctrl_msg_hdr_offset + MCTP_CTRL_MSG_HEADER_LEN; + let mctp_hdr_start = self.mctp_hdr_offset(); + let mctp_ctrl_hdr_start = mctp_hdr_start + MCTP_HDR_SIZE; + let msg_payload_start = mctp_ctrl_hdr_start + MCTP_CTRL_MSG_HEADER_LEN; let req_buf = &msg_buf[MCTP_CTRL_MSG_HEADER_LEN..]; let mctp_ctrl_cmd: MCTPCtrlCmd = mctp_ctrl_msg_hdr.cmd().into(); @@ -207,7 +212,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { .map_or(Err(ErrorCode::NOMEM), |resp_buf| { let result = match mctp_ctrl_cmd { MCTPCtrlCmd::SetEID => mctp_ctrl_cmd - .process_set_endpoint_id(req_buf, &mut resp_buf[msg_payload_offset..]) + .process_set_endpoint_id(req_buf, &mut resp_buf[msg_payload_start..]) .map(|eid| { if let Some(eid) = eid { self.set_local_eid(eid); @@ -216,7 +221,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { MCTPCtrlCmd::GetEID => mctp_ctrl_cmd.process_get_endpoint_id( self.get_local_eid(), - &mut resp_buf[msg_payload_offset..], + &mut resp_buf[msg_payload_start..], ), MCTPCtrlCmd::GetMsgTypeSupport => return Err(ErrorCode::NOSUPPORT), @@ -228,12 +233,13 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { let res = self .fill_mctp_ctrl_hdr_resp( mctp_ctrl_msg_hdr_resp, - &mut resp_buf[mctp_ctrl_msg_hdr_offset..], + &mut resp_buf[mctp_ctrl_hdr_start + ..mctp_ctrl_hdr_start + MCTP_CTRL_MSG_HEADER_LEN], ) .and_then(|_| { self.fill_mctp_hdr_resp( mctp_hdr_resp, - &mut resp_buf[mctp_hdr_offset..], + &mut resp_buf[mctp_hdr_start..mctp_hdr_start + MCTP_HDR_SIZE], ) }); @@ -259,28 +265,34 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { }) } - // fn receive_packet( - // &self, - // mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, - // msg_type: MessageType, - // pkt_payload: &[u8], - // ) -> Result<(), ErrorCode> { - // let msg_type_val = msg_type as u8; - // let rx_state = self - // .receiver_list - // .iter() - // .find(|rx_state| rx_state.receive_pending(msg_type_val)); - - // if let Some(rx_state) = rx_state { - - // if mctp_hdr. - // rx_state.is_m(mctp_hdr, pkt_payload); - // } else { - // println!("MuxMCTPDriver: No matching receive request found. Dropping packet."); - // } - // Ok(()) - - // } + fn send_next_packet(&self, cur_sender: &'a MCTPTxState<'a, M>) { + let mut tx_pkt = SubSliceMut::new(self.tx_pkt_buffer.take().unwrap()); + let mctp_hdr_offset = self.mctp_hdr_offset(); + let pkt_end_offset = self.get_mtu(); + + // set the window of the subslice for MCTP header and the payload + tx_pkt.slice(mctp_hdr_offset..pkt_end_offset); + + match cur_sender.next_packet(&mut tx_pkt, self.local_eid.get()) { + Ok(len) => { + tx_pkt.reset(); + match self + .mctp_device + .transmit(tx_pkt.take(), len + mctp_hdr_offset) + { + Ok(_) => (), + Err((err, buf)) => { + println!("MuxMCTPDriver: Failed to transmit {:?}", err); + self.tx_pkt_buffer.replace(buf); + } + } + } + Err(err) => { + println!("MuxMCTPDriver: Failed to start transmit {:?}", err); + self.tx_pkt_buffer.replace(tx_pkt.take()); + } + } + } fn process_first_packet( &self, @@ -322,13 +334,12 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { } None => { println!("MuxMCTPDriver: No matching receive request found. Dropping packet."); - return; } } } - fn get_total_hdr_size(&self) -> usize { - MCTP_HDR_SIZE + self.mctp_device.get_hdr_size() + fn mctp_hdr_offset(&self) -> usize { + self.mctp_device.get_hdr_size() } } diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index df6bb9b..3fa1bbd 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -78,8 +78,8 @@ impl<'a> MCTPRxState<'a> { pub fn is_receive_expected(&self, msg_type: MessageType) -> bool { let msg_types = self.msg_types.get(); - for i in 0..MAX_MESSAGE_TYPES { - if msg_type as u8 == msg_types[i] { + for exp_msg_type in msg_types.iter() { + if msg_type as u8 == *exp_msg_type { return true; } } @@ -130,9 +130,9 @@ impl<'a> MCTPRxState<'a> { pub fn end_receive(&self) { if let Some(msg_terminus) = self.msg_terminus.take() { let msg_tag = if msg_terminus.tag_owner == 1 { - msg_terminus.msg_tag & MCTP_TAG_MASK | MCTP_TAG_OWNER + (msg_terminus.msg_tag & MCTP_TAG_MASK) | MCTP_TAG_OWNER } else { - msg_terminus.msg_tag + msg_terminus.msg_tag & MCTP_TAG_MASK }; self.client.map(|client| { self.msg_payload.map(|msg_payload| { @@ -159,13 +159,16 @@ impl<'a> MCTPRxState<'a> { return; } - if pkt_payload.len() == 0 { - println!("MCTPMuxDriver - Received packet with no payload. Dropping packet."); + let pkt_payload_len = pkt_payload.len(); + + if pkt_payload.is_empty() + || (pkt_payload_len > 0 + && pkt_payload_len > self.msg_payload.map_or(0, |msg_payload| msg_payload.len())) + { + println!("MCTPMuxDriver - Received bad packet length. Dropping packet."); return; } - let pkt_payload_len = pkt_payload.len(); - let msg_terminus = MsgTerminus { msg_type: msg_type as u8, msg_tag: mctp_hdr.msg_tag(), @@ -177,11 +180,17 @@ impl<'a> MCTPRxState<'a> { self.msg_terminus.replace(msg_terminus); - self.msg_payload.take().map(|msg_payload| { - msg_payload[..pkt_payload.len()].copy_from_slice(pkt_payload); - self.msg_payload.replace(msg_payload); - }); - self.msg_size.set(pkt_payload_len); + self.msg_payload + .take() + .map(|msg_payload| { + msg_payload[..pkt_payload.len()].copy_from_slice(pkt_payload); + self.msg_payload.replace(msg_payload); + self.msg_size.set(pkt_payload_len); + }) + .unwrap_or_else(|| { + // This should never happen + panic!("MCTPMuxDriver - Received first packet without buffer. Dropping packet."); + }); if mctp_hdr.eom() == 1 { self.end_receive(); diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs index 5bd3ca5..54a46aa 100644 --- a/runtime/capsules/src/mctp/send.rs +++ b/runtime/capsules/src/mctp/send.rs @@ -1,6 +1,10 @@ +use crate::mctp::base_protocol::{MCTPHeader, MCTP_HDR_SIZE}; +use crate::mctp::common::{MCTP_TAG_MASK, MCTP_TAG_OWNER}; use crate::mctp::mux::MuxMCTPDriver; use crate::mctp::transport_binding::MCTPTransportBinding; +use zerocopy::IntoBytes; + use core::cell::Cell; use kernel::collections::list::{ListLink, ListNode}; @@ -9,19 +13,26 @@ use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; /// The trait that provides an interface to send the MCTP messages to MCTP kernel stack. -pub trait MCTPSender { +pub trait MCTPSender<'a> { /// Sets the client for the `MCTPSender` instance. - fn set_client(&self, client: &dyn MCTPTxClient); + fn set_client(&self, client: &'a dyn MCTPTxClient); /// Sends the message to the MCTP kernel stack. - fn send_msg(&self, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>); + fn send_msg( + &'a self, + dest_eid: u8, + msg_tag: u8, + msg_payload: SubSliceMut<'static, u8>, + ) -> Result<(), SubSliceMut<'static, u8>>; } /// This trait is implemented by client to get notified after message is sent. pub trait MCTPTxClient { fn send_done( &self, - msg_tag: Option, + dest_eid: u8, + msg_type: u8, + msg_tag: u8, result: Result<(), ErrorCode>, msg_payload: SubSliceMut<'static, u8>, ); @@ -34,9 +45,10 @@ pub struct MCTPTxState<'a, M: MCTPTransportBinding<'a>> { /// Destination EID dest_eid: Cell, /// Message type - msg_type: Cell, + // msg_type: Cell, /// msg_tag for the message being packetized msg_tag: Cell, + tag_owner: Cell, /// Current packet sequence pkt_seq: Cell, /// Offset into the message buffer @@ -54,3 +66,97 @@ impl<'a, M: MCTPTransportBinding<'a>> ListNode<'a, MCTPTxState<'a, M>> for MCTPT &self.next } } + +impl<'a, M: MCTPTransportBinding<'a>> MCTPSender<'a> for MCTPTxState<'a, M> { + fn set_client(&self, client: &'a dyn MCTPTxClient) { + self.client.set(client); + } + + fn send_msg( + &'a self, + dest_eid: u8, + msg_tag: u8, + msg_payload: SubSliceMut<'static, u8>, + ) -> Result<(), SubSliceMut<'static, u8>> { + self.dest_eid.set(dest_eid); + // Response message should not have the owner bit set + if msg_tag & MCTP_TAG_OWNER == 0 { + self.msg_tag.set(msg_tag & MCTP_TAG_MASK); + self.tag_owner.set(false); + } else { + let msg_tag = self.mctp_mux_sender.get_next_msg_tag(); + self.msg_tag.set(msg_tag | MCTP_TAG_OWNER); + self.tag_owner.set(true); + } + self.msg_payload.replace(msg_payload); + self.pkt_seq.set(0); + self.offset.set(0); + + self.mctp_mux_sender.add_sender(self); + + Ok(()) + } +} + +impl<'a, M: MCTPTransportBinding<'a>> MCTPTxState<'a, M> { + pub fn new(mctp_mux_sender: &'a MuxMCTPDriver<'a, M>) -> MCTPTxState<'a, M> { + MCTPTxState { + mctp_mux_sender, + dest_eid: Cell::new(0), + tag_owner: Cell::new(false), + msg_tag: Cell::new(0), + pkt_seq: Cell::new(0), + offset: Cell::new(0), + client: OptionalCell::empty(), + next: ListLink::empty(), + msg_payload: MapCell::empty(), + } + } + + pub fn is_eom(&self) -> bool { + self.offset.get() >= self.msg_payload.map_or(0, |msg_payload| msg_payload.len()) + } + + pub fn next_packet( + &self, + pkt_buf: &mut SubSliceMut<'static, u8>, + src_eid: u8, + ) -> Result { + if self.is_eom() { + return Err(ErrorCode::FAIL); + } + + self.msg_payload + .map_or(Err(ErrorCode::FAIL), |msg_payload| { + let max_payload_len = pkt_buf.len() - MCTP_HDR_SIZE; + let total_msg_len = msg_payload.len(); + let offset = self.offset.get(); + let pkt_seq = self.pkt_seq.get(); + let remaining_len = total_msg_len - offset; + let som = if offset == 0 { 1 } else { 0 }; + let eom = if remaining_len <= max_payload_len { + 1 + } else { + 0 + }; + let copy_len = max_payload_len.min(remaining_len); + + let mut mctp_hdr = MCTPHeader::new(); + mctp_hdr.prepare_header( + self.dest_eid.get(), + src_eid, + som, + eom, + self.pkt_seq.get(), + self.tag_owner.get() as u8, + self.msg_tag.get(), + ); + pkt_buf[0..MCTP_HDR_SIZE].copy_from_slice(mctp_hdr.as_bytes()); + pkt_buf[MCTP_HDR_SIZE..MCTP_HDR_SIZE + copy_len] + .copy_from_slice(&msg_payload[offset..offset + copy_len]); + self.offset.set(offset + copy_len); + self.pkt_seq.set((pkt_seq + 1) % 4); + Ok(copy_len + MCTP_HDR_SIZE) + }) + } +} From 3bd8a5568041f34bda346d1c83b6207103252176 Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Sat, 14 Dec 2024 13:38:05 -0800 Subject: [PATCH 03/11] instantiate the syscall drivers for SPDM, PLDM and vendor defined PCI message types --- docs/src/mctp.md | 2 +- runtime/capsules/src/mctp/base_protocol.rs | 42 ++++-- runtime/capsules/src/mctp/common.rs | 7 - runtime/capsules/src/mctp/control_msg.rs | 9 +- runtime/capsules/src/mctp/driver.rs | 146 +++++++++++---------- runtime/capsules/src/mctp/mod.rs | 1 - runtime/capsules/src/mctp/mux.rs | 23 +++- runtime/capsules/src/mctp/recv.rs | 20 +-- runtime/capsules/src/mctp/send.rs | 39 +++++- runtime/src/board.rs | 56 +++++++- runtime/src/components/mctp_driver.rs | 109 +++++++++++++++ runtime/src/components/mctp_mux.rs | 3 +- runtime/src/components/mod.rs | 1 + 13 files changed, 339 insertions(+), 119 deletions(-) delete mode 100644 runtime/capsules/src/mctp/common.rs create mode 100644 runtime/src/components/mctp_driver.rs diff --git a/docs/src/mctp.md b/docs/src/mctp.md index 7a58009..a7822d1 100644 --- a/docs/src/mctp.md +++ b/docs/src/mctp.md @@ -283,7 +283,7 @@ struct OperationCtx { #[derive(default)] pub struct App { - pending_op_ctx: OperationCtx, + pending_rx: OperationCtx, bound_msg_type : u8, } diff --git a/runtime/capsules/src/mctp/base_protocol.rs b/runtime/capsules/src/mctp/base_protocol.rs index 6f640e4..62dc0b4 100644 --- a/runtime/capsules/src/mctp/base_protocol.rs +++ b/runtime/capsules/src/mctp/base_protocol.rs @@ -8,7 +8,14 @@ use bitfield::bitfield; use zerocopy::{FromBytes, Immutable, IntoBytes}; +pub const MCTP_TAG_OWNER: u8 = 0x08; +pub const MCTP_TAG_MASK: u8 = 0x07; + +pub const MCTP_PROTOCOL_VERSION_1: u8 = 0x01; +pub const MCTP_PROTOCOL_VERSION_MASK: u8 = 0x0F; + pub const MCTP_HDR_SIZE: usize = 4; +pub const MCTP_BROADCAST_EID: u8 = 0xFF; bitfield! { #[repr(C)] @@ -66,27 +73,44 @@ impl MCTPHeader<[u8; MCTP_HDR_SIZE]> { #[derive(Debug, PartialEq, Clone, Copy)] pub enum MessageType { - MCTPControl, - PLDM, - SPDM, - SSPDM, - VendorDefinedPCI, + MctpControl = 0, + Pldm = 1, + Spdm = 5, + SecureSPDM = 6, + VendorDefinedPCI = 0x7E, Invalid, } +// impl Into for MessageType { +// fn into(self) -> u8 { +// match self { +// MessageType::MctpControl => 0, +// MessageType::Pldm => 1, +// MessageType::Spdm => 5, +// MessageType::SecureSPDM => 6, +// MessageType::VendorDefinedPCI => 0x7E, +// MessageType::Invalid => 0xFF, +// } +// } +// } + impl From for MessageType { fn from(val: u8) -> MessageType { match val { - 0 => MessageType::MCTPControl, - 1 => MessageType::PLDM, - 5 => MessageType::SPDM, - 6 => MessageType::SSPDM, + 0 => MessageType::MctpControl, + 1 => MessageType::Pldm, + 5 => MessageType::Spdm, + 6 => MessageType::SecureSPDM, 0x7E => MessageType::VendorDefinedPCI, _ => MessageType::Invalid, } } } +pub fn valid_eid(eid: u8) -> bool { + eid != MCTP_BROADCAST_EID && !(1..7).contains(&eid) +} + #[cfg(test)] mod tests { use super::*; diff --git a/runtime/capsules/src/mctp/common.rs b/runtime/capsules/src/mctp/common.rs deleted file mode 100644 index dc46a47..0000000 --- a/runtime/capsules/src/mctp/common.rs +++ /dev/null @@ -1,7 +0,0 @@ -// Licensed under the Apache-2.0 license - -pub const MCTP_TAG_OWNER: u8 = 0x08; -pub const MCTP_TAG_MASK: u8 = 0x07; - -pub const MCTP_PROTOCOL_VERSION_1: u8 = 0x01; -pub const MCTP_PROTOCOL_VERSION_MASK: u8 = 0x0F; diff --git a/runtime/capsules/src/mctp/control_msg.rs b/runtime/capsules/src/mctp/control_msg.rs index 94e5e59..04c8781 100644 --- a/runtime/capsules/src/mctp/control_msg.rs +++ b/runtime/capsules/src/mctp/control_msg.rs @@ -4,10 +4,9 @@ use bitfield::bitfield; use kernel::ErrorCode; use zerocopy::{FromBytes, Immutable, IntoBytes}; -pub const MCTP_CTRL_MSG_HEADER_LEN: usize = 3; +use crate::mctp::base_protocol::valid_eid; -const MCTP_NULL_EID: u8 = 0; -const MCTP_BROADCAST_EID: u8 = 0xFF; +pub const MCTP_CTRL_MSG_HEADER_LEN: usize = 3; bitfield! { #[repr(C)] @@ -108,7 +107,7 @@ impl MCTPCtrlCmd { match op { SetEIDOp::SetEID | SetEIDOp::ForceEID => { - if eid == MCTP_NULL_EID || eid == MCTP_BROADCAST_EID || (1..7).contains(&eid) { + if eid == 0 || !valid_eid(eid) { completion_code = CmdCompletionCode::ErrorInvalidData; } else { // TODO: Check if rejected case needs to be handled @@ -318,7 +317,7 @@ mod tests { let mut msg_hdr = MCTPCtrlMsgHdr::new(); msg_hdr.prepare_header(0, 0, 0, MCTPCtrlCmd::SetEID.to_u8()); assert_eq!(msg_hdr.ic(), 0); - assert_eq!(msg_hdr.msg_type(), MessageType::MCTPControl as u8); + assert_eq!(msg_hdr.msg_type(), MessageType::MctpControl as u8); assert_eq!(msg_hdr.rq(), 0); assert_eq!(msg_hdr.datagram(), 0); assert_eq!(msg_hdr.instance_id(), 0); diff --git a/runtime/capsules/src/mctp/driver.rs b/runtime/capsules/src/mctp/driver.rs index b0147c9..13fb14f 100644 --- a/runtime/capsules/src/mctp/driver.rs +++ b/runtime/capsules/src/mctp/driver.rs @@ -1,15 +1,13 @@ // Licensed under the Apache-2.0 license +use crate::mctp::base_protocol::*; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; -use crate::mctp::common::*; - use core::cell::Cell; use core::fmt::Write; use romtime::println; -use kernel::debug; use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer}; use kernel::syscall::{CommandReturn, SyscallDriver}; @@ -17,11 +15,7 @@ use kernel::utilities::cells::MapCell; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::{ErrorCode, ProcessId}; -pub const MAX_MESSAGE_TYPES: usize = 2; - -pub const SPDM_MAX_MESSAGE_SIZE: usize = 4098; -pub const PLDM_MAX_MESSAGE_SIZE: usize = 4098; -pub const VENDOR_DEFINED_PCI_MAX_MESSAGE_SIZE: usize = 4098; +pub const MCTP_MAX_MESSAGE_SIZE: usize = 4098; pub const MCTP_SPDM_DRIVER_NUM: usize = 0xA0000; pub const MCTP_PLDM_DRIVER_NUM: usize = 0xA0001; @@ -58,11 +52,8 @@ mod rw_allow { } enum OpType { - SendReq, - SendResp, - ReceiveReq, - ReceiveResp, - Idle, + Tx, + Rx, } struct OpContext { @@ -73,22 +64,31 @@ struct OpContext { } impl OpContext { - fn is_match(&self, msg_tag: u8, peer_eid: u8, msg_type: u8) -> bool { + fn for_me(&self, msg_tag: u8, peer_eid: u8, msg_type: u8) -> bool { if self.msg_type != msg_type { return false; } match self.op_type { - OpType::ReceiveReq => { - if msg_tag & MCTP_TAG_OWNER != 0 { - return true; + OpType::Rx => { + if self.msg_tag == msg_tag { + if msg_tag & MCTP_TAG_OWNER != 0 { + return true; + } + if self.peer_eid == peer_eid { + return true; + } } } - OpType::ReceiveResp => { - if self.msg_tag & MCTP_TAG_MASK == msg_tag && self.peer_eid == peer_eid { - return true; + OpType::Tx => { + if self.peer_eid == peer_eid { + if msg_tag & MCTP_TAG_OWNER != 0 { + return true; + } + if self.msg_tag == msg_tag { + return true; + } } } - _ => {} } false } @@ -96,7 +96,7 @@ impl OpContext { #[derive(Default)] pub struct App { - pending_op_ctx: Option, + pending_rx: Option, pending_tx: Option, } @@ -109,7 +109,7 @@ pub struct MCTPDriver<'a> { AllowRwCount<{ rw_allow::COUNT }>, >, current_app: Cell>, - msg_types: [u8; MAX_MESSAGE_TYPES], + msg_types: &'static [MessageType], max_msg_size: usize, kernel_msg_buf: MapCell>, } @@ -123,7 +123,7 @@ impl<'a> MCTPDriver<'a> { AllowRoCount<{ ro_allow::COUNT }>, AllowRwCount<{ rw_allow::COUNT }>, >, - msg_types: [u8; MAX_MESSAGE_TYPES], + msg_types: &'static [MessageType], max_msg_size: usize, msg_buf: SubSliceMut<'static, u8>, ) -> MCTPDriver<'a> { @@ -138,13 +138,43 @@ impl<'a> MCTPDriver<'a> { } fn supported_msg_type(&self, msg_type: u8) -> bool { - for i in 0..MAX_MESSAGE_TYPES { - if msg_type == self.msg_types[i] { + for mtype in self.msg_types.iter() { + if msg_type == *mtype as u8 { return true; } } false } + + fn validate_args( + &self, + command_num: usize, + arg1: usize, + arg2: usize, + ) -> Result<(u8, u8, u8), ErrorCode> { + // arg1 is always peer_eid + let peer_eid = arg1 as u8; + + if !valid_eid(peer_eid) { + Err(ErrorCode::INVAL)?; + } + + // lower 8 bits of arg2 is always msg_type + let msg_type = (arg2 & 0xFF) as u8; + if !self.supported_msg_type(msg_type) { + Err(ErrorCode::INVAL)?; + } + let msg_tag = (arg2 >> 8 & 0xFF) as u8; + + // Receive Request message or send Request message + if ((command_num == 1 || command_num == 3) && msg_tag != MCTP_TAG_OWNER) + || ((command_num == 2 || command_num == 4) && msg_tag & MCTP_TAG_OWNER != 0) + { + Err(ErrorCode::INVAL)?; + } + + Ok((peer_eid, msg_type, msg_tag)) + } } impl<'a> SyscallDriver for MCTPDriver<'a> { @@ -155,51 +185,30 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { arg2: usize, process_id: ProcessId, ) -> CommandReturn { - // lower 8 bits of arg2 is always msg_type - let msg_type = arg2 as u8; - if !self.supported_msg_type(msg_type) { - return CommandReturn::failure(ErrorCode::INVAL); - } + let (peer_eid, msg_type, msg_tag) = match self.validate_args(command_num, arg1, arg2) { + Ok((peer_eid, msg_type, msg_tag)) => (peer_eid, msg_type, msg_tag), + Err(e) => return CommandReturn::failure(e), + }; match command_num { 0 => CommandReturn::success(), - // Receive Request Message - // arg1: peer_eid - // arg2: msg_type - 1 => self - .apps - .enter(process_id, |app, _| { - app.pending_op_ctx = Some(OpContext { - msg_tag: MCTP_TAG_OWNER, - peer_eid: arg1 as u8, - msg_type, - op_type: OpType::ReceiveReq, - }); - CommandReturn::success() - }) - .unwrap_or_else(|err| CommandReturn::failure(err.into())), - // Receive Response Message - // arg1: peer_eid - // arg2: msg_tag << 8 | msg_type - 2 => self + // 1: Receive Request Message + // 2: Receive Response Message + 1 | 2 => self .apps .enter(process_id, |app, _| { - let peer_eid = arg1 as u8; - let msg_tag = ((arg2 >> 8) & 0xFF) as u8; - - app.pending_op_ctx = Some(OpContext { + app.pending_rx = Some(OpContext { msg_tag, peer_eid, msg_type, - op_type: OpType::ReceiveResp, + op_type: OpType::Rx, }); CommandReturn::success() }) .unwrap_or_else(|err| CommandReturn::failure(err.into())), - // Send Request Message - // arg1: dest_eid - // arg2: msg_type - 3 => { + // 3. Send Request Message + // 4: Send Response Message + 3 | 4 => { let result = self .apps .enter(process_id, |app, kernel_data| { @@ -224,17 +233,18 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { kernel_msg_buf.slice(0..wpayload.len()); match self.sender.send_msg( + msg_type, dest_eid, - MCTP_TAG_OWNER, + msg_tag, kernel_msg_buf, ) { Ok(_) => { println!("MCTPDriver: send_msg success"); app.pending_tx = Some(OpContext { - msg_tag: MCTP_TAG_OWNER, + msg_tag, peer_eid: dest_eid, msg_type, - op_type: OpType::SendReq, + op_type: OpType::Tx, }); self.current_app.set(Some(process_id)); Ok(()) @@ -264,10 +274,6 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { Err(e) => CommandReturn::failure(e), } } - 4 => { - debug!("MCTPDriver::command: 4. TODO Send Response Message"); - CommandReturn::success() - } 5 => CommandReturn::success_u32(self.max_msg_size as u32), _ => CommandReturn::failure(ErrorCode::NOSUPPORT), } @@ -292,7 +298,7 @@ impl<'a> MCTPTxClient for MCTPDriver<'a> { if let Some(process_id) = self.current_app.get() { _ = self.apps.enter(process_id, |app, up_calls| { if let Some(op_ctx) = app.pending_tx.as_mut() { - if op_ctx.is_match(msg_tag, dest_eid, msg_type) { + if op_ctx.for_me(msg_tag, dest_eid, msg_type) { app.pending_tx = None; let msg_info = (msg_type as usize) << 8 | (msg_tag as usize); up_calls @@ -316,8 +322,8 @@ impl<'a> MCTPTxClient for MCTPDriver<'a> { impl<'a> MCTPRxClient for MCTPDriver<'a> { fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { self.apps.each(|_, app, kernel_data| { - if let Some(op_ctx) = app.pending_op_ctx.as_mut() { - if op_ctx.is_match(msg_tag, src_eid, msg_type) { + if let Some(op_ctx) = app.pending_rx.as_mut() { + if op_ctx.for_me(msg_tag, src_eid, msg_type) { let res = kernel_data .get_readwrite_processbuffer(rw_allow::MESSAGE_READ) .and_then(|read| { @@ -333,7 +339,7 @@ impl<'a> MCTPRxClient for MCTPDriver<'a> { .unwrap_or(Ok(())); if res.is_ok() { - app.pending_op_ctx = None; + app.pending_rx = None; let msg_info = (msg_type as usize) << 8 | (msg_tag as usize); kernel_data .schedule_upcall( diff --git a/runtime/capsules/src/mctp/mod.rs b/runtime/capsules/src/mctp/mod.rs index 86b3a4e..ceced4f 100644 --- a/runtime/capsules/src/mctp/mod.rs +++ b/runtime/capsules/src/mctp/mod.rs @@ -1,7 +1,6 @@ // Licensed under the Apache-2.0 license pub mod base_protocol; -pub mod common; pub mod control_msg; pub mod driver; pub mod mux; diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index e22ed25..8a75d39 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -344,8 +344,21 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { } impl<'a, M: MCTPTransportBinding<'a>> TransportTxClient for MuxMCTPDriver<'a, M> { - fn send_done(&self, tx_buffer: &'static mut [u8], _result: Result<(), ErrorCode>) { + fn send_done(&self, tx_buffer: &'static mut [u8], result: Result<(), ErrorCode>) { self.tx_pkt_buffer.replace(tx_buffer); + + let mut cur_sender = self.sender_list.head(); + if let Some(sender) = cur_sender { + if sender.is_eom() { + sender.send_done(result); + self.sender_list.pop_head(); + cur_sender = self.sender_list.head(); + } + } + + if let Some(cur_sender) = cur_sender { + self.send_next_packet(cur_sender); + }; } } @@ -360,7 +373,7 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> let (mctp_header, msg_type, payload_offset) = self.interpret_packet(&rx_buffer[0..len]); if let Some(msg_type) = msg_type { match msg_type { - MessageType::MCTPControl => { + MessageType::MctpControl => { if mctp_header.tag_owner() == 1 && mctp_header.som() == 1 && mctp_header.eom() == 1 @@ -371,9 +384,9 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> println!("MuxMCTPDriver: Invalid MCTP Control message. Dropping packet."); } } - MessageType::PLDM - | MessageType::SPDM - | MessageType::SSPDM + MessageType::Pldm + | MessageType::Spdm + | MessageType::SecureSPDM | MessageType::VendorDefinedPCI => { self.process_first_packet( mctp_header, diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index 3fa1bbd..5d3b697 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -1,3 +1,5 @@ +// Licensed under the Apache-2.0 license + use crate::mctp::base_protocol::MCTPHeader; use core::fmt::Write; @@ -8,9 +10,7 @@ use core::cell::Cell; use kernel::collections::list::{ListLink, ListNode}; use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; -use super::base_protocol::{MessageType, MCTP_HDR_SIZE}; -use super::common::{MCTP_TAG_MASK, MCTP_TAG_OWNER}; -use super::driver::MAX_MESSAGE_TYPES; +use super::base_protocol::{MessageType, MCTP_HDR_SIZE, MCTP_TAG_MASK, MCTP_TAG_OWNER}; /// This trait is implemented to get notified of the messages received /// on corresponding message_type. @@ -23,7 +23,7 @@ pub trait MCTPRxClient { pub struct MCTPRxState<'a> { /// Message assembly context msg_terminus: MapCell, - msg_types: Cell<[u8; MAX_MESSAGE_TYPES]>, + msg_types: Cell<&'static [MessageType]>, // // /// Source EID // // source_eid: Cell, // /// message type @@ -60,7 +60,7 @@ struct MsgTerminus { impl<'a> MCTPRxState<'a> { pub fn new( rx_msg_buf: &'static mut [u8], - message_types: [u8; MAX_MESSAGE_TYPES], + message_types: &'static [MessageType], ) -> MCTPRxState<'static> { MCTPRxState { msg_terminus: MapCell::empty(), @@ -79,7 +79,7 @@ impl<'a> MCTPRxState<'a> { pub fn is_receive_expected(&self, msg_type: MessageType) -> bool { let msg_types = self.msg_types.get(); for exp_msg_type in msg_types.iter() { - if msg_type as u8 == *exp_msg_type { + if msg_type == *exp_msg_type { return true; } } @@ -109,7 +109,7 @@ impl<'a> MCTPRxState<'a> { let offset = self.msg_size.get(); let end_offset = offset + pkt_payload.len(); if end_offset > self.msg_payload.map_or(0, |msg_payload| msg_payload.len()) { - println!("MCTPMuxDriver - Received packet with payload length greater than buffer size. Dropping packet."); + println!("MuxMCTPDriver - Received packet with payload length greater than buffer size. Dropping packet."); self.msg_size.set(0); return; } @@ -155,7 +155,7 @@ impl<'a> MCTPRxState<'a> { pkt_payload: &[u8], ) { if mctp_hdr.som() != 1 { - println!("MCTPMuxDriver - Received first packet without SOM. Dropping packet."); + println!("MuxMCTPDriver - Received first packet without SOM. Dropping packet."); return; } @@ -165,7 +165,7 @@ impl<'a> MCTPRxState<'a> { || (pkt_payload_len > 0 && pkt_payload_len > self.msg_payload.map_or(0, |msg_payload| msg_payload.len())) { - println!("MCTPMuxDriver - Received bad packet length. Dropping packet."); + println!("MuxMCTPDriver - Received bad packet length. Dropping packet."); return; } @@ -189,7 +189,7 @@ impl<'a> MCTPRxState<'a> { }) .unwrap_or_else(|| { // This should never happen - panic!("MCTPMuxDriver - Received first packet without buffer. Dropping packet."); + panic!("MuxMCTPDriver - Received first packet without buffer. Dropping packet."); }); if mctp_hdr.eom() == 1 { diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs index 54a46aa..574200a 100644 --- a/runtime/capsules/src/mctp/send.rs +++ b/runtime/capsules/src/mctp/send.rs @@ -1,5 +1,6 @@ -use crate::mctp::base_protocol::{MCTPHeader, MCTP_HDR_SIZE}; -use crate::mctp::common::{MCTP_TAG_MASK, MCTP_TAG_OWNER}; +// Licensed under the Apache-2.0 license + +use crate::mctp::base_protocol::{MCTPHeader, MCTP_HDR_SIZE, MCTP_TAG_MASK, MCTP_TAG_OWNER}; use crate::mctp::mux::MuxMCTPDriver; use crate::mctp::transport_binding::MCTPTransportBinding; @@ -7,6 +8,9 @@ use zerocopy::IntoBytes; use core::cell::Cell; +use core::fmt::Write; +use romtime::println; + use kernel::collections::list::{ListLink, ListNode}; use kernel::utilities::cells::{MapCell, OptionalCell}; use kernel::utilities::leasable_buffer::SubSliceMut; @@ -20,6 +24,7 @@ pub trait MCTPSender<'a> { /// Sends the message to the MCTP kernel stack. fn send_msg( &'a self, + msg_type: u8, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>, @@ -45,7 +50,7 @@ pub struct MCTPTxState<'a, M: MCTPTransportBinding<'a>> { /// Destination EID dest_eid: Cell, /// Message type - // msg_type: Cell, + msg_type: Cell, /// msg_tag for the message being packetized msg_tag: Cell, tag_owner: Cell, @@ -74,6 +79,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPSender<'a> for MCTPTxState<'a, M> { fn send_msg( &'a self, + msg_type: u8, dest_eid: u8, msg_tag: u8, msg_payload: SubSliceMut<'static, u8>, @@ -88,6 +94,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPSender<'a> for MCTPTxState<'a, M> { self.msg_tag.set(msg_tag | MCTP_TAG_OWNER); self.tag_owner.set(true); } + self.msg_type.set(msg_type); self.msg_payload.replace(msg_payload); self.pkt_seq.set(0); self.offset.set(0); @@ -105,6 +112,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPTxState<'a, M> { dest_eid: Cell::new(0), tag_owner: Cell::new(false), msg_tag: Cell::new(0), + msg_type: Cell::new(0), pkt_seq: Cell::new(0), offset: Cell::new(0), client: OptionalCell::empty(), @@ -123,7 +131,8 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPTxState<'a, M> { src_eid: u8, ) -> Result { if self.is_eom() { - return Err(ErrorCode::FAIL); + println!("MCTPTxState - Error!! next_packet: EOM reached"); + Err(ErrorCode::FAIL)?; } self.msg_payload @@ -159,4 +168,26 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPTxState<'a, M> { Ok(copy_len + MCTP_HDR_SIZE) }) } + + pub fn send_done(&self, result: Result<(), ErrorCode>) { + self.client.map(|client| { + if let Some(msg_payload) = self.msg_payload.take() { + let msg_tag = self.msg_tag.get() + | if self.tag_owner.get() { + MCTP_TAG_OWNER + } else { + 0 + }; + client.send_done( + self.dest_eid.get(), + self.msg_type.get(), + msg_tag, + result, + msg_payload, + ); + } else { + println!("MCTPTxState - Error!! send_done: msg_payload is None"); + } + }); + } } diff --git a/runtime/src/board.rs b/runtime/src/board.rs index 590b15d..85ead63 100644 --- a/runtime/src/board.rs +++ b/runtime/src/board.rs @@ -4,9 +4,8 @@ use crate::chip::VeeRDefaultPeripherals; use crate::chip::TIMERS; use crate::components as runtime_components; use crate::timers::InternalTimers; + use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm}; -use capsules_runtime::mctp::mux::MuxMCTPDriver; -use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; use core::ptr::{addr_of, addr_of_mut}; use kernel::capabilities; use kernel::component::Component; @@ -76,8 +75,9 @@ struct VeeR { scheduler: &'static CooperativeSched<'static>, scheduler_timer: &'static VirtualSchedulerTimer>>, - // Temporarily add MCTP mux to the platform struct until driver is ready - mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, + mctp_spdm: &'static capsules_runtime::mctp::driver::MCTPDriver<'static>, + mctp_pldm: &'static capsules_runtime::mctp::driver::MCTPDriver<'static>, + mctp_vendor_def_pci: &'static capsules_runtime::mctp::driver::MCTPDriver<'static>, } /// Mapping of integer syscalls to objects that implement syscalls. @@ -90,6 +90,11 @@ impl SyscallDriverLookup for VeeR { capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)), capsules_core::console::DRIVER_NUM => f(Some(self.console)), capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)), + capsules_runtime::mctp::driver::MCTP_SPDM_DRIVER_NUM => f(Some(self.mctp_spdm)), + capsules_runtime::mctp::driver::MCTP_PLDM_DRIVER_NUM => f(Some(self.mctp_pldm)), + capsules_runtime::mctp::driver::MCTP_VENDOR_DEFINED_PCI_DRIVER_NUM => { + f(Some(self.mctp_vendor_def_pci)) + } _ => f(None), } } @@ -225,6 +230,45 @@ pub unsafe fn main() { let mctp_mux = runtime_components::mctp_mux::MCTPMuxComponent::new(&peripherals.i3c) .finalize(crate::mctp_mux_component_static!(MCTPI3CBinding)); + let mctp_spdm_msg_types = static_init!( + [capsules_runtime::mctp::base_protocol::MessageType; 2], + [ + capsules_runtime::mctp::base_protocol::MessageType::Spdm, + capsules_runtime::mctp::base_protocol::MessageType::SecureSPDM, + ] + ); + let mctp_spdm = runtime_components::mctp_driver::MCTPDriverComponent::new( + board_kernel, + capsules_runtime::mctp::driver::MCTP_SPDM_DRIVER_NUM, + mctp_mux, + mctp_spdm_msg_types, + ) + .finalize(crate::mctp_driver_component_static!()); + + let mctp_pldm_msg_types = static_init!( + [capsules_runtime::mctp::base_protocol::MessageType; 1], + [capsules_runtime::mctp::base_protocol::MessageType::Pldm] + ); + let mctp_pldm = runtime_components::mctp_driver::MCTPDriverComponent::new( + board_kernel, + capsules_runtime::mctp::driver::MCTP_PLDM_DRIVER_NUM, + mctp_mux, + mctp_pldm_msg_types, + ) + .finalize(crate::mctp_driver_component_static!()); + + let mctp_vendor_def_pci_msg_types = static_init!( + [capsules_runtime::mctp::base_protocol::MessageType; 1], + [capsules_runtime::mctp::base_protocol::MessageType::VendorDefinedPCI] + ); + let mctp_vendor_def_pci = runtime_components::mctp_driver::MCTPDriverComponent::new( + board_kernel, + capsules_runtime::mctp::driver::MCTP_VENDOR_DEFINED_PCI_DRIVER_NUM, + mctp_mux, + mctp_vendor_def_pci_msg_types, + ) + .finalize(crate::mctp_driver_component_static!()); + peripherals.init(); // Need to enable all interrupts for Tock Kernel @@ -269,7 +313,9 @@ pub unsafe fn main() { lldb, scheduler, scheduler_timer, - mctp_mux, + mctp_spdm, + mctp_pldm, + mctp_vendor_def_pci, } ); diff --git a/runtime/src/components/mctp_driver.rs b/runtime/src/components/mctp_driver.rs new file mode 100644 index 0000000..4bf2802 --- /dev/null +++ b/runtime/src/components/mctp_driver.rs @@ -0,0 +1,109 @@ +// Licensed under the Apache-2.0 license + +//! Component for initializing the MCTP driver. +//! +//! This module provides MCTPDriverComponent, which sets up the syscall driver for MCTP, +//! enabling user space applications to send and receive MCTP messages. +//! +//! Each application that handles specific MCTP message types will utilize the MCTP driver +//! instantiated for that particular message type. +//! +//! Usage +//! ----- +//! ```rust +//! let mctp_driver = MCTPDriverComponent::new().finalize( +//! ``` +//! +//! + +use capsules_runtime::mctp::base_protocol::MessageType; +use capsules_runtime::mctp::driver::{MCTPDriver, MCTP_MAX_MESSAGE_SIZE}; +use capsules_runtime::mctp::mux::MuxMCTPDriver; +use capsules_runtime::mctp::recv::MCTPRxState; +use capsules_runtime::mctp::send::MCTPSender; +use capsules_runtime::mctp::send::MCTPTxState; +use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; + +use kernel::capabilities; +use kernel::component::Component; +use kernel::utilities::leasable_buffer::SubSliceMut; + +use core::mem::MaybeUninit; + +// Setup static space for the objects. +#[macro_export] +macro_rules! mctp_driver_component_static { + () => {{ + use capsules_runtime::mctp::driver::MCTPDriver; + use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; + use capsules_runtime::mctp::recv::MCTPRxState; + use capsules_runtime::mctp::send::MCTPTxState; + use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; + + let tx_state = kernel::static_buf!(MCTPTxState<'static, MCTPI3CBinding<'static>>); + let rx_state = kernel::static_buf!(MCTPRxState<'static>); + let rx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); + let tx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); + let mctp_driver = kernel::static_buf!(MCTPDriver<'static>); + (tx_state, rx_state, rx_msg_buf, tx_msg_buf, mctp_driver) + }}; +} + +pub struct MCTPDriverComponent { + board_kernel: &'static kernel::Kernel, + driver_num: usize, + mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, + msg_types: &'static [MessageType], +} + +impl MCTPDriverComponent { + pub fn new( + board_kernel: &'static kernel::Kernel, + driver_num: usize, + mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, + msg_types: &'static [MessageType], + ) -> Self { + Self { + board_kernel, + driver_num, + mctp_mux, + msg_types, + } + } +} + +impl Component for MCTPDriverComponent { + type StaticInput = ( + &'static mut MaybeUninit>>, + &'static mut MaybeUninit>, + &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, + &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, + &'static mut MaybeUninit>, + ); + type Output = &'static MCTPDriver<'static>; + + fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output { + let grant_cap = kernel::create_capability!(capabilities::MemoryAllocationCapability); + + let rx_msg_buf = static_buffer.2.write([0; MCTP_MAX_MESSAGE_SIZE]); + let tx_msg_buf = static_buffer.3.write([0; MCTP_MAX_MESSAGE_SIZE]); + + let tx_state = static_buffer.0.write(MCTPTxState::new(self.mctp_mux)); + let rx_state = static_buffer + .1 + .write(MCTPRxState::new(rx_msg_buf, self.msg_types)); + + let mctp_driver = static_buffer.4.write(MCTPDriver::new( + tx_state, + self.board_kernel.create_grant(self.driver_num, &grant_cap), + self.msg_types, + MCTP_MAX_MESSAGE_SIZE, + SubSliceMut::new(tx_msg_buf), + )); + + tx_state.set_client(mctp_driver); + rx_state.set_client(mctp_driver); + self.mctp_mux.add_receiver(rx_state); + mctp_driver + } +} diff --git a/runtime/src/components/mctp_mux.rs b/runtime/src/components/mctp_mux.rs index 5e48a0f..4c1dd36 100644 --- a/runtime/src/components/mctp_mux.rs +++ b/runtime/src/components/mctp_mux.rs @@ -13,8 +13,7 @@ //! use capsules_runtime::mctp::mux::MuxMCTPDriver; -use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; -use capsules_runtime::mctp::transport_binding::MCTPTransportBinding; +use capsules_runtime::mctp::transport_binding::{MCTPI3CBinding, MCTPTransportBinding}; use i3c_driver::core::MAX_READ_WRITE_SIZE; diff --git a/runtime/src/components/mod.rs b/runtime/src/components/mod.rs index f4d5e0f..a09112b 100644 --- a/runtime/src/components/mod.rs +++ b/runtime/src/components/mod.rs @@ -2,4 +2,5 @@ //! Components for the Caliptra MCU runtime. +pub mod mctp_driver; pub mod mctp_mux; From 76fd074ee8d38616dea964c35e3fff3f72f1fe8c Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Sat, 14 Dec 2024 16:42:39 -0800 Subject: [PATCH 04/11] cleanup and add funtion headers --- runtime/capsules/src/mctp/base_protocol.rs | 13 --- runtime/capsules/src/mctp/mux.rs | 2 +- runtime/capsules/src/mctp/recv.rs | 129 +++++++++++++-------- runtime/capsules/src/mctp/send.rs | 18 ++- 4 files changed, 97 insertions(+), 65 deletions(-) diff --git a/runtime/capsules/src/mctp/base_protocol.rs b/runtime/capsules/src/mctp/base_protocol.rs index 62dc0b4..cb2e90d 100644 --- a/runtime/capsules/src/mctp/base_protocol.rs +++ b/runtime/capsules/src/mctp/base_protocol.rs @@ -81,19 +81,6 @@ pub enum MessageType { Invalid, } -// impl Into for MessageType { -// fn into(self) -> u8 { -// match self { -// MessageType::MctpControl => 0, -// MessageType::Pldm => 1, -// MessageType::Spdm => 5, -// MessageType::SecureSPDM => 6, -// MessageType::VendorDefinedPCI => 0x7E, -// MessageType::Invalid => 0xFF, -// } -// } -// } - impl From for MessageType { fn from(val: u8) -> MessageType { match val { diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index 8a75d39..ac063f4 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -273,7 +273,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { // set the window of the subslice for MCTP header and the payload tx_pkt.slice(mctp_hdr_offset..pkt_end_offset); - match cur_sender.next_packet(&mut tx_pkt, self.local_eid.get()) { + match cur_sender.fill_next_packet(&mut tx_pkt, self.local_eid.get()) { Ok(len) => { tx_pkt.reset(); match self diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index 5d3b697..041d44c 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -19,21 +19,11 @@ pub trait MCTPRxClient { } /// Receive state -#[allow(dead_code)] pub struct MCTPRxState<'a> { /// Message assembly context msg_terminus: MapCell, + /// Expected message types msg_types: Cell<&'static [MessageType]>, - // // /// Source EID - // // source_eid: Cell, - // /// message type - // msg_type: Cell, - // /// msg_tag for the message being assembled - // msg_tag: Cell, - /// Current packet sequence - // pkt_seq: Cell, - /// msg_size in the message buffer - msg_size: Cell, /// Client (implements the MCTPRxClient trait) client: OptionalCell<&'a dyn MCTPRxClient>, /// Message buffer @@ -55,6 +45,7 @@ struct MsgTerminus { tag_owner: u8, start_payload_len: usize, pkt_seq: u8, + msg_size: usize, } impl<'a> MCTPRxState<'a> { @@ -65,7 +56,6 @@ impl<'a> MCTPRxState<'a> { MCTPRxState { msg_terminus: MapCell::empty(), msg_types: Cell::new(message_types), - msg_size: Cell::new(0), client: OptionalCell::empty(), msg_payload: TakeCell::new(rx_msg_buf), next: ListLink::empty(), @@ -76,6 +66,13 @@ impl<'a> MCTPRxState<'a> { self.client.set(client); } + /// Checks if a message of the given type is expected to be received. + /// + /// # Arguments + /// 'msg_type' - The message type to check if it is expected. + /// + /// # Returns + /// True if the message type is expected, false otherwise. pub fn is_receive_expected(&self, msg_type: MessageType) -> bool { let msg_types = self.msg_types.get(); for exp_msg_type in msg_types.iter() { @@ -86,6 +83,15 @@ impl<'a> MCTPRxState<'a> { false } + /// Checks from the received MCTP header if the next packet belongs to + /// the current message being assembled. + /// + /// # Arguments + /// 'mctp_hdr' - The MCTP header of the received packet. + /// 'pkt_payload_len' - The length of the payload of the received packet. + /// + /// # Returns + /// True if the next packet belongs to the current message, false otherwise. pub fn is_next_packet( &self, mctp_hdr: &MCTPHeader<[u8; MCTP_HDR_SIZE]>, @@ -104,29 +110,43 @@ impl<'a> MCTPRxState<'a> { .unwrap_or(false) } + /// Receives the next packet of the message being assembled. + /// If the packet is the last one, the message is delivered to the client + /// by calling the `receive` method of the client. + /// + /// # Arguments + /// 'mctp_hdr' - The MCTP header of the received packet. + /// 'pkt_payload' - The payload of the received packet. pub fn receive_next(&self, mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, pkt_payload: &[u8]) { if let Some(mut msg_terminus) = self.msg_terminus.take() { - let offset = self.msg_size.get(); + let offset = msg_terminus.msg_size; let end_offset = offset + pkt_payload.len(); if end_offset > self.msg_payload.map_or(0, |msg_payload| msg_payload.len()) { - println!("MuxMCTPDriver - Received packet with payload length greater than buffer size. Dropping packet."); - self.msg_size.set(0); + println!("MuxMCTPDriver - Received packet with payload length greater than buffer size. Reset assembly."); return; } - self.msg_payload.map(|msg_payload| { - msg_payload[offset..end_offset].copy_from_slice(pkt_payload); - self.msg_size.set(end_offset); - }); - msg_terminus.pkt_seq = mctp_hdr.next_pkt_seq(); - self.msg_terminus.replace(msg_terminus); - } + self.msg_payload + .map(|msg_payload| { + msg_payload[offset..end_offset].copy_from_slice(pkt_payload); + msg_terminus.msg_size = end_offset; + msg_terminus.pkt_seq = mctp_hdr.next_pkt_seq(); + self.msg_terminus.replace(msg_terminus); + }) + .unwrap_or_else(|| { + println!( + "MuxMCTPDriver - No msg buffer in receive next. This should never happen." + ); + }); - if mctp_hdr.eom() == 1 { - self.end_receive(); + if mctp_hdr.eom() == 1 { + self.end_receive(); + } } } + /// Called at the end of the message assembly to deliver the message to the client. + /// The message terminus state is set to None after the message is delivered. pub fn end_receive(&self) { if let Some(msg_terminus) = self.msg_terminus.take() { let msg_tag = if msg_terminus.tag_owner == 1 { @@ -134,20 +154,35 @@ impl<'a> MCTPRxState<'a> { } else { msg_terminus.msg_tag & MCTP_TAG_MASK }; - self.client.map(|client| { - self.msg_payload.map(|msg_payload| { - client.receive( - msg_terminus.source_eid, - msg_terminus.msg_type, - msg_tag, - msg_payload, - self.msg_size.get(), + self.client + .map(|client| { + self.msg_payload.map(|msg_payload| { + client.receive( + msg_terminus.source_eid, + msg_terminus.msg_type, + msg_tag, + msg_payload, + msg_terminus.msg_size, + ); + }); + }) + .unwrap_or_else(|| { + println!( + "MuxMCTPDriver - No msg buffer in end receive. This should never happen." ); }); - }); } } + /// Called when the first packet of a message is received. + /// The message terminus state is initialized with the current context. + /// The previous message assembly state will be lost and a new message assembly + /// will be started. + /// + /// # Arguments + /// 'mctp_hdr' - The MCTP header of the received packet. + /// 'msg_type' - The message type of the received packet. + /// 'pkt_payload' - The payload of the received packet. pub fn start_receive( &self, mctp_hdr: MCTPHeader<[u8; MCTP_HDR_SIZE]>, @@ -169,29 +204,27 @@ impl<'a> MCTPRxState<'a> { return; } - let msg_terminus = MsgTerminus { - msg_type: msg_type as u8, - msg_tag: mctp_hdr.msg_tag(), - source_eid: mctp_hdr.src_eid(), - tag_owner: mctp_hdr.tag_owner(), - start_payload_len: pkt_payload_len, - pkt_seq: mctp_hdr.next_pkt_seq(), - }; - - self.msg_terminus.replace(msg_terminus); - self.msg_payload - .take() .map(|msg_payload| { msg_payload[..pkt_payload.len()].copy_from_slice(pkt_payload); - self.msg_payload.replace(msg_payload); - self.msg_size.set(pkt_payload_len); + + let msg_terminus = MsgTerminus { + msg_type: msg_type as u8, + msg_tag: mctp_hdr.msg_tag(), + source_eid: mctp_hdr.src_eid(), + tag_owner: mctp_hdr.tag_owner(), + start_payload_len: pkt_payload_len, + pkt_seq: mctp_hdr.next_pkt_seq(), + msg_size: pkt_payload_len, + }; + self.msg_terminus.replace(msg_terminus); }) .unwrap_or_else(|| { // This should never happen - panic!("MuxMCTPDriver - Received first packet without buffer. Dropping packet."); + println!("MuxMCTPDriver - Received first packet without buffer. This should never happen."); }); + // Single packet message if mctp_hdr.eom() == 1 { self.end_receive(); } diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs index 574200a..061bf08 100644 --- a/runtime/capsules/src/mctp/send.rs +++ b/runtime/capsules/src/mctp/send.rs @@ -44,7 +44,6 @@ pub trait MCTPTxClient { } /// Send state for MCTP -#[allow(dead_code)] pub struct MCTPTxState<'a, M: MCTPTransportBinding<'a>> { mctp_mux_sender: &'a MuxMCTPDriver<'a, M>, /// Destination EID @@ -125,13 +124,22 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPTxState<'a, M> { self.offset.get() >= self.msg_payload.map_or(0, |msg_payload| msg_payload.len()) } - pub fn next_packet( + /// Fills the next packet in the packet buffer. + /// The packet buffer should be large enough to hold the MCTP header and the payload. + /// + /// # Arguments + /// `pkt_buf` - The buffer to fill the next packet. + /// `src_eid` - The source EID to be used in the MCTP header. + /// + /// # Returns + /// The number of bytes filled in the packet buffer on success, error code otherwise. + pub fn fill_next_packet( &self, pkt_buf: &mut SubSliceMut<'static, u8>, src_eid: u8, ) -> Result { if self.is_eom() { - println!("MCTPTxState - Error!! next_packet: EOM reached"); + println!("MCTPTxState - Error!! fill_next_packet: EOM reached"); Err(ErrorCode::FAIL)?; } @@ -169,6 +177,10 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPTxState<'a, M> { }) } + /// Informs the client that the message has been sent. + /// + /// # Arguments + /// `result` - The result of the send operation. pub fn send_done(&self, result: Result<(), ErrorCode>) { self.client.map(|client| { if let Some(msg_payload) = self.msg_payload.take() { From 0a28289f802d702c0ef60e811c40e3e87dae131d Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Mon, 16 Dec 2024 14:20:20 -0800 Subject: [PATCH 05/11] mctp stack test framework draft --- .gitignore | 1 + runtime/capsules/src/lib.rs | 2 + runtime/capsules/src/mctp/mux.rs | 2 +- runtime/capsules/src/test/mock_mctp.rs | 101 ++++++++++++++++++ runtime/capsules/src/test/mod.rs | 3 + runtime/src/board.rs | 16 +-- runtime/src/components/mctp_driver.rs | 10 +- runtime/src/components/mock_mctp.rs | 85 +++++++++++++++ runtime/src/main.rs | 3 - runtime/src/{ => tests}/flash_ctrl_test.rs | 0 .../{tests.rs => tests/i3c_target_test.rs} | 0 runtime/src/tests/mctp_test.rs | 7 ++ runtime/src/tests/mod.rs | 2 + 13 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 runtime/capsules/src/test/mock_mctp.rs create mode 100644 runtime/capsules/src/test/mod.rs create mode 100644 runtime/src/components/mock_mctp.rs rename runtime/src/{ => tests}/flash_ctrl_test.rs (100%) rename runtime/src/{tests.rs => tests/i3c_target_test.rs} (100%) create mode 100644 runtime/src/tests/mctp_test.rs create mode 100644 runtime/src/tests/mod.rs diff --git a/.gitignore b/.gitignore index 02f4ec7..f78c56b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ book # flash file dummy_flash.bin +primary_flash diff --git a/runtime/capsules/src/lib.rs b/runtime/capsules/src/lib.rs index 1e13506..44a8544 100644 --- a/runtime/capsules/src/lib.rs +++ b/runtime/capsules/src/lib.rs @@ -3,4 +3,6 @@ #![cfg_attr(target_arch = "riscv32", no_std)] #![forbid(unsafe_code)] +pub mod test; + pub mod mctp; diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index ac063f4..91d85df 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -349,7 +349,7 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportTxClient for MuxMCTPDriver<'a, M> let mut cur_sender = self.sender_list.head(); if let Some(sender) = cur_sender { - if sender.is_eom() { + if sender.is_eom() || result.is_err() { sender.send_done(result); self.sender_list.pop_head(); cur_sender = self.sender_list.head(); diff --git a/runtime/capsules/src/test/mock_mctp.rs b/runtime/capsules/src/test/mock_mctp.rs new file mode 100644 index 0000000..bf4b53e --- /dev/null +++ b/runtime/capsules/src/test/mock_mctp.rs @@ -0,0 +1,101 @@ +// Licensed under the Apache-2.0 license + +use crate::mctp::control_msg::MCTP_CTRL_MSG_HEADER_LEN; +use crate::mctp::mux::MuxMCTPDriver; +use crate::mctp::recv::{MCTPRxClient, MCTPRxState}; +use crate::mctp::base_protocol::{MCTP_TAG_OWNER, MCTP_TAG_MASK}; +use crate::mctp::send::{MCTPSender, MCTPTxClient, MCTPTxState}; + +use core::ptr::addr_of_mut; +use core::cell::Cell; + +use kernel::utilities::cells::MapCell; +use kernel::utilities::leasable_buffer::SubSliceMut; +use kernel::ErrorCode; + +const MCTP_TEST_MSG_TYPE: u8 = 0xAA; +// const MCTP_TEST_LOCAL_EID : u8 = 0x10; +const MCTP_TEST_REMOTE_EID : u8 = 0x20; +const MCTP_TEST_MSG_SIZE : usize = 256; + +static mut MCTP_TEST_PAYLOAD: [u8; MCTP_TEST_MSG_SIZE] = { + let mut v: [u8; MCTP_TEST_MSG_SIZE] = [0; MCTP_TEST_MSG_SIZE]; + v[0] = MCTP_TEST_MSG_TYPE; + let mut i = 1; + while i < 256 { + v[i] = i as u8; + i += 1; + } + v +}; + +pub struct MockMctp<'a> { + mctp_sender: &'a dyn MCTPSender<'a>, + mctp_msg_buf: MapCell>, + msg_type: u8, + msg_tag: Cell, +} + +impl<'a> MockMctp<'a> { + pub fn new( + mctp_sender: &'a dyn MCTPSender<'a>, + mctp_msg_buf: MapCell>, + ) -> Self { + Self { + mctp_sender, + mctp_msg_buf, + msg_type : MCTP_TEST_MSG_TYPE, + msg_tag: Cell::new(0), + } + } + + fn prepare_send_data(&self) { + self.mctp_msg_buf.map(|buf| { + let test_data = unsafe {&mut *addr_of_mut!(MCTP_TEST_PAYLOAD)}; + buf.reset(); + buf[..].copy_from_slice(test_data); + buf.slice(..test_data.len()); + }); + } + + pub fn run_send_echo_test(&self) { + self.prepare_send_data(); + assert!(self.mctp_msg_buf.map(|buf| buf.len()).unwrap() == MCTP_TEST_MSG_SIZE); + self.mctp_sender.send_msg(self.msg_type, MCTP_TEST_REMOTE_EID,MCTP_TAG_OWNER, self.mctp_msg_buf.take().unwrap()).unwrap(); + } + +} + +impl<'a> MCTPRxClient for MockMctp<'a> { + fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { + println!("Received message from EID: {} with message type: {} and message tag: {}", src_eid, msg_type, msg_tag); + + assert!(msg_type == self.msg_type); + assert!(src_eid == MCTP_TEST_REMOTE_EID); + assert!(msg_len == self.mctp_msg_buf.map(|buf| buf.len()).unwrap()); + + + self.mctp_msg_buf.map(|buf| { + assert!(buf[..msg_len] == msg_payload[..msg_len]); + }); + + runtime::io::exit_emulator(0); + + } +} + +impl<'a> MCTPTxClient for MockMctp<'a> { + fn send_done(&self, dest_eid: u8, + msg_type: u8, + msg_tag: u8, + result: Result<(), ErrorCode>, + mut msg_payload: SubSliceMut<'static, u8>,) { + assert!(result == Ok(())); + assert!(dest_eid == MCTP_TEST_REMOTE_EID); + assert!(msg_type == self.msg_type); + self.msg_tag.set(msg_tag); + msg_payload.reset(); + self.mctp_msg_buf.replace(msg_payload); + println!("Message sent"); + } +} diff --git a/runtime/capsules/src/test/mod.rs b/runtime/capsules/src/test/mod.rs new file mode 100644 index 0000000..6bc16c5 --- /dev/null +++ b/runtime/capsules/src/test/mod.rs @@ -0,0 +1,3 @@ +// Licensed under the Apache-2.0 license + +pub mod mock_mctp; diff --git a/runtime/src/board.rs b/runtime/src/board.rs index 85ead63..e3aa7ed 100644 --- a/runtime/src/board.rs +++ b/runtime/src/board.rs @@ -352,20 +352,24 @@ pub unsafe fn main() { // Run any requested test let exit = if cfg!(feature = "test-i3c-simple") { debug!("Executing test-i3c-simple"); - crate::tests::test_i3c_simple() + crate::tests::i3c_target_test::test_i3c_simple() } else if cfg!(feature = "test-i3c-constant-writes") { debug!("Executing test-i3c-constant-writes"); - crate::tests::test_i3c_constant_writes() + crate::tests::i3c_target_test::test_i3c_constant_writes() } else if cfg!(feature = "test-flash-ctrl-init") { debug!("Executing test-flash-ctrl-init"); - crate::flash_ctrl_test::test_flash_ctrl_init() + crate::tests::flash_ctrl_test::test_flash_ctrl_init() } else if cfg!(feature = "test-flash-ctrl-read-write-page") { debug!("Executing test-flash-ctrl-read-write-page"); - crate::flash_ctrl_test::test_flash_ctrl_read_write_page() + crate::tests::flash_ctrl_test::test_flash_ctrl_read_write_page() } else if cfg!(feature = "test-flash-ctrl-erase-page") { debug!("Executing test-flash-ctrl-erase-page"); - crate::flash_ctrl_test::test_flash_ctrl_erase_page() - } else { + crate::tests::flash_ctrl_test::test_flash_ctrl_erase_page() + } else if cfg!(feature = "test-mctp-mux") { + debug!("Executing test-mctp-mux"); + crate::tests::mctp_mux::test_mctp_mux() + } + else { None }; if let Some(exit) = exit { diff --git a/runtime/src/components/mctp_driver.rs b/runtime/src/components/mctp_driver.rs index 4bf2802..7dcc216 100644 --- a/runtime/src/components/mctp_driver.rs +++ b/runtime/src/components/mctp_driver.rs @@ -11,10 +11,14 @@ //! Usage //! ----- //! ```rust -//! let mctp_driver = MCTPDriverComponent::new().finalize( +//! let spdm_mctp_driver = MCTPDriverComponent::new( +//! board_kernel, +//! capsules_runtime::mctp::driver::MCTP_SPDM_DRIVER_NUM, +//! mctp_mux, +//! mctp_spdm_msg_types, +//! ) +//! .finalize(mctp_driver_component_static!()); //! ``` -//! -//! use capsules_runtime::mctp::base_protocol::MessageType; use capsules_runtime::mctp::driver::{MCTPDriver, MCTP_MAX_MESSAGE_SIZE}; diff --git a/runtime/src/components/mock_mctp.rs b/runtime/src/components/mock_mctp.rs new file mode 100644 index 0000000..d136709 --- /dev/null +++ b/runtime/src/components/mock_mctp.rs @@ -0,0 +1,85 @@ +use capsules_runtime::mctp::mux::MuxMCTPDriver; +use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; +use capsules_runtime::mctp::base_protocol::MessageType; +use capsules_runtime::test::mock_mctp::MockMctp; + +use kernel::component::Component; + +use core::mem::MaybeUninit; + + +#[macro_export] +macro_rules! mock_mctp_component_static { + () => {{ + use capsules_runtime::test::mock_mctp::MockMctp; + use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; + use capsules_runtime::mctp::recv::MCTPRxState; + use capsules_runtime::mctp::send::MCTPTxState; + use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; + + let tx_state = kernel::static_buf!(MCTPTxState<'static, MCTPI3CBinding<'static>>); + let rx_state = kernel::static_buf!(MCTPRxState<'static>); + let rx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); + let tx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); + let mock_mctp = kernel::static_buf!(MockMctp<'static>); + (tx_state, rx_state, rx_msg_buf, tx_msg_buf, mock_mctp) + }}; +} + + +pub struct MockMctpComponent { + mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, + msg_types: &'static [u8], +} + +impl MockMctpComponent { + pub fn new( + mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, + msg_types: &'static [u8], + ) -> Self { + Self { + mctp_mux, + msg_types, + } + } +} + +impl component for MockMctpComponent { + type StaticInput = ( + &'static mut MaybeUninit>>, + &'static mut MaybeUninit>, + &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, + &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, + &'static mut MaybeUninit>, + ); + type Output = &'static MockMctp<'static>; + + fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output { + let rx_msg_buf = static_buffer.2.write([0; MCTP_MAX_MESSAGE_SIZE]); + let tx_msg_buf = static_buffer.3.write([0; MCTP_MAX_MESSAGE_SIZE]); + + let tx_state = static_buffer.0.write(MCTPTxState::new( + self.mctp_mux, + )); + + let rx_state = static_buffer.1.write(MCTPRxState::new( + rx_msg_buf, + self.msg_types, + )); + + let mock_mctp = static_buffer.4.write(MockMctp::new( + tx_state, + rx_state, + rx_msg_buf, + tx_msg_buf, + self.msg_types, + )); + + tx_state.set_client(mock_mctp); + rx_state.set_client(mock_mctp); + self.mctp_mux.add_receiver(rx_state); + + mock_mctp + } +} + diff --git a/runtime/src/main.rs b/runtime/src/main.rs index e05d0b5..4915f3c 100644 --- a/runtime/src/main.rs +++ b/runtime/src/main.rs @@ -30,9 +30,6 @@ mod timers; #[cfg(target_arch = "riscv32")] mod flash_ctrl; -#[cfg(target_arch = "riscv32")] -#[allow(unused_imports)] -mod flash_ctrl_test; #[cfg(target_arch = "riscv32")] pub use board::*; diff --git a/runtime/src/flash_ctrl_test.rs b/runtime/src/tests/flash_ctrl_test.rs similarity index 100% rename from runtime/src/flash_ctrl_test.rs rename to runtime/src/tests/flash_ctrl_test.rs diff --git a/runtime/src/tests.rs b/runtime/src/tests/i3c_target_test.rs similarity index 100% rename from runtime/src/tests.rs rename to runtime/src/tests/i3c_target_test.rs diff --git a/runtime/src/tests/mctp_test.rs b/runtime/src/tests/mctp_test.rs new file mode 100644 index 0000000..0d7cb01 --- /dev/null +++ b/runtime/src/tests/mctp_test.rs @@ -0,0 +1,7 @@ + +use capsules_runtime::mctp::test::MockMctp; +use crate::components::mock_mctp::MockMctpComponent; + +pub fn test_mctp_send_loop_back() { + +} diff --git a/runtime/src/tests/mod.rs b/runtime/src/tests/mod.rs new file mode 100644 index 0000000..e3fb8bf --- /dev/null +++ b/runtime/src/tests/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod flash_ctrl_test; +pub(crate) mod i3c_target_test; From 6d19d078563601db8947abcadb43d4f84f2ee27b Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Mon, 16 Dec 2024 22:10:20 -0800 Subject: [PATCH 06/11] refactor tests --- emulator/app/Cargo.toml | 1 + emulator/app/src/i3c_socket.rs | 218 +++++++----------- emulator/app/src/main.rs | 19 +- emulator/app/src/tests/mctp_ctrl_cmd.rs | 82 ++++++- emulator/app/src/tests/mctp_loopback.rs | 14 ++ emulator/periph/Cargo.toml | 1 + runtime/Cargo.toml | 1 + runtime/capsules/src/mctp/driver.rs | 11 +- runtime/capsules/src/mctp/mux.rs | 14 ++ runtime/capsules/src/mctp/recv.rs | 12 +- runtime/capsules/src/mctp/send.rs | 4 + .../capsules/src/mctp/transport_binding.rs | 5 + runtime/capsules/src/test/mctp.rs | 135 +++++++++++ runtime/capsules/src/test/mock_mctp.rs | 101 -------- runtime/capsules/src/test/mod.rs | 2 +- runtime/i3c/src/core.rs | 4 + runtime/src/board.rs | 23 +- runtime/src/components/mctp_driver.rs | 5 +- runtime/src/components/mock_mctp.rs | 60 ++--- runtime/src/components/mod.rs | 1 + runtime/src/tests/mctp_test.rs | 61 ++++- runtime/src/tests/mod.rs | 1 + tests/integration/src/lib.rs | 1 + 23 files changed, 474 insertions(+), 302 deletions(-) create mode 100644 emulator/app/src/tests/mctp_loopback.rs create mode 100644 runtime/capsules/src/test/mctp.rs delete mode 100644 runtime/capsules/src/test/mock_mctp.rs diff --git a/emulator/app/Cargo.toml b/emulator/app/Cargo.toml index f6e8307..3e8ce1d 100644 --- a/emulator/app/Cargo.toml +++ b/emulator/app/Cargo.toml @@ -38,3 +38,4 @@ test-flash-ctrl-init = [] test-flash-ctrl-read-write-page = [] test-flash-ctrl-erase-page = [] test-mctp-ctrl-cmds = ["emulator-periph/test-mctp-ctrl-cmds"] +test-mctp-send-loopback = ["emulator-periph/test-mctp-send-loopback"] diff --git a/emulator/app/src/i3c_socket.rs b/emulator/app/src/i3c_socket.rs index 61f5797..f87a009 100644 --- a/emulator/app/src/i3c_socket.rs +++ b/emulator/app/src/i3c_socket.rs @@ -146,6 +146,7 @@ fn handle_i3c_socket_connection( Err(e) => panic!("Error reading message from socket: {}", e), } if let Ok(response) = bus_response_rx.recv_timeout(Duration::from_millis(10)) { + println!("Received response from bus: {:?}", response); let data_len = response.resp.data.len(); if data_len > 255 { panic!("Cannot write more than 255 bytes to socket"); @@ -162,11 +163,16 @@ fn handle_i3c_socket_connection( } } +pub(crate) trait TestTrait { + fn run_test(&mut self, running: Arc, stream: &mut TcpStream, target_addr: u8); + fn is_passed(&self) -> bool; +} + pub(crate) fn run_tests( running: Arc, port: u16, target_addr: DynamicI3cAddress, - tests: Vec, + tests: Vec>, ) { let running_clone = running.clone(); let addr = SocketAddr::from(([127, 0, 0, 1], port)); @@ -178,7 +184,7 @@ pub(crate) fn run_tests( } #[derive(Debug, Clone)] -enum TestState { +pub enum TestState { Start, SendPrivateWrite, WaitForIbi, @@ -186,138 +192,12 @@ enum TestState { Finish, } -#[derive(Debug, Clone)] -pub(crate) struct Test { - name: String, - state: TestState, - pvt_write_data: Vec, - pvt_read_data: Vec, - passed: bool, -} - -impl Test { - pub(crate) fn new(name: &str, pvt_write_data: Vec, pvt_read_data: Vec) -> Self { - Self { - name: name.to_string(), - state: TestState::Start, - pvt_write_data, - pvt_read_data, - passed: false, - } - } - - fn is_passed(&self) -> bool { - self.passed - } - - fn check_response(&mut self, data: &[u8]) { - if data.len() == self.pvt_read_data.len() && data == self.pvt_read_data { - self.passed = true; - } - } - - fn run_test(&mut self, running: Arc, stream: &mut TcpStream, target_addr: u8) { - stream.set_nonblocking(true).unwrap(); - while running.load(Ordering::Relaxed) { - match self.state { - TestState::Start => { - println!("Starting test: {}", self.name); - self.state = TestState::SendPrivateWrite; - } - TestState::SendPrivateWrite => self.send_private_write(stream, target_addr), - TestState::WaitForIbi => self.receive_ibi(stream, target_addr), - TestState::ReceivePrivateRead => self.receive_private_read(stream, target_addr), - TestState::Finish => { - println!( - "Test {} : {}", - self.name, - if self.passed { "PASSED" } else { "FAILED" } - ); - break; - } - } - } - } - - fn send_private_write(&mut self, stream: &mut TcpStream, target_addr: u8) { - let addr: u8 = target_addr; - let pvt_write_data = self.pvt_write_data.as_slice(); - - let pec = calculate_crc8(addr << 1, pvt_write_data); - - let mut pkt = Vec::new(); - pkt.extend_from_slice(pvt_write_data); - pkt.push(pec); - - let pvt_write_cmd = prepare_private_write_cmd(addr, pkt.len() as u16); - stream.set_nonblocking(false).unwrap(); - stream.write_all(&pvt_write_cmd).unwrap(); - stream.set_nonblocking(true).unwrap(); - stream.write_all(&pkt).unwrap(); - self.state = TestState::WaitForIbi; - } - - fn receive_ibi(&mut self, stream: &mut TcpStream, target_addr: u8) { - let mut out_header_bytes: [u8; 6] = [0u8; 6]; - match stream.read_exact(&mut out_header_bytes) { - Ok(()) => { - let outdata: OutgoingHeader = transmute!(out_header_bytes); - if outdata.ibi != 0 && outdata.from_addr == target_addr { - let pvt_read_cmd = prepare_private_read_cmd(target_addr); - stream.set_nonblocking(false).unwrap(); - stream.write_all(&pvt_read_cmd).unwrap(); - stream.set_nonblocking(true).unwrap(); - self.state = TestState::ReceivePrivateRead; - } - } - Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} - Err(e) => panic!("Error reading message from socket: {}", e), - } - } - - fn receive_private_read(&mut self, stream: &mut TcpStream, target_addr: u8) { - let mut out_header_bytes = [0u8; 6]; - match stream.read_exact(&mut out_header_bytes) { - Ok(()) => { - let outdata: OutgoingHeader = transmute!(out_header_bytes); - if target_addr != outdata.from_addr { - return; - } - let resp_desc = outdata.response_descriptor; - let data_len = resp_desc.data_length() as usize; - let mut data = vec![0u8; data_len]; - - stream.set_nonblocking(false).unwrap(); - stream - .read_exact(&mut data) - .expect("Failed to read message from socket"); - stream.set_nonblocking(true).unwrap(); - - let pec = calculate_crc8((target_addr << 1) | 1, &data[..data.len() - 1]); - if pec == data[data.len() - 1] { - self.check_response(&data[..data.len() - 1]); - } else { - println!( - "Received data with invalid CRC8: calclulated {:X} != received {:X}", - pec, - data[data.len() - 1] - ); - } - - self.state = TestState::Finish; - } - Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} - Err(e) => panic!("Error reading message from socket: {}", e), - } - } -} - struct TestRunner { stream: TcpStream, target_addr: u8, passed: usize, running: Arc, - tests: Vec, + tests: Vec>, } impl TestRunner { @@ -325,7 +205,7 @@ impl TestRunner { stream: TcpStream, target_addr: u8, running: Arc, - tests: Vec, + tests: Vec>, ) -> Self { Self { stream, @@ -352,6 +232,84 @@ impl TestRunner { } } + +pub fn send_private_write(stream: &mut TcpStream, target_addr: u8, data: Vec) -> bool { + // println!("Sending private write to target: {}", target_addr); + let addr: u8 = target_addr; + + let pec = calculate_crc8(addr << 1, data.as_slice()); + + let mut pkt = Vec::new(); + pkt.extend_from_slice(data.as_slice()); + pkt.push(pec); + + let pvt_write_cmd = prepare_private_write_cmd(addr, pkt.len() as u16); + stream.set_nonblocking(false).unwrap(); + stream.write_all(&pvt_write_cmd).unwrap(); + stream.set_nonblocking(true).unwrap(); + stream.write_all(&pkt).unwrap(); + true +} + +pub fn receive_ibi(stream: &mut TcpStream, target_addr: u8) -> bool { + // println!("Waiting for IBI from target: {}", target_addr); + let mut out_header_bytes: [u8; 6] = [0u8; 6]; + match stream.read_exact(&mut out_header_bytes) { + Ok(()) => { + let outdata: OutgoingHeader = transmute!(out_header_bytes); + if outdata.ibi != 0 && outdata.from_addr == target_addr { + let pvt_read_cmd = prepare_private_read_cmd(target_addr); + stream.set_nonblocking(false).unwrap(); + stream.write_all(&pvt_read_cmd).unwrap(); + stream.set_nonblocking(true).unwrap(); + return true; + } + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} + Err(e) => panic!("Error reading message from socket: {}", e), + } + false +} + +pub fn receive_private_read(stream: &mut TcpStream, target_addr: u8) -> Option> { + // println!("Receiving private read from target: {}", target_addr); + let mut out_header_bytes = [0u8; 6]; + match stream.read_exact(&mut out_header_bytes) { + Ok(()) => { + let outdata: OutgoingHeader = transmute!(out_header_bytes); + if target_addr != outdata.from_addr { + return None; + } + let resp_desc = outdata.response_descriptor; + let data_len = resp_desc.data_length() as usize; + let mut data = vec![0u8; data_len]; + + stream.set_nonblocking(false).unwrap(); + stream + .read_exact(&mut data) + .expect("Failed to read message from socket"); + stream.set_nonblocking(true).unwrap(); + + let pec = calculate_crc8((target_addr << 1) | 1, &data[..data.len() - 1]); + if pec != data[data.len() - 1] { + println!( + "Received data with invalid CRC8: calclulated {:X} != received {:X}", + pec, + data[data.len() - 1] + ); + return None; + } + + return Some(data[..data.len() - 1].to_vec()); + + // self.state = TestState::Finish; + } + Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} + Err(e) => panic!("Error reading message from socket: {}", e), + } + None +} + fn prepare_private_write_cmd(to_addr: u8, data_len: u16) -> [u8; 9] { let mut write_cmd = ReguDataTransferCommand::read_from_bytes(&[0; 8]).unwrap(); write_cmd.set_rnw(0); diff --git a/emulator/app/src/main.rs b/emulator/app/src/main.rs index da0f7b7..785e6ff 100644 --- a/emulator/app/src/main.rs +++ b/emulator/app/src/main.rs @@ -362,7 +362,7 @@ fn run(cli: Emulator, capture_uart_output: bool) -> io::Result> { if cfg!(feature = "test-mctp-ctrl-cmds") { i3c_controller.start(); println!( - "Starting test thread for testing target {:?}", + "Starting test-mctp-ctrl-cmds test thread for testing target {:?}", i3c.get_dynamic_address().unwrap() ); @@ -373,6 +373,23 @@ fn run(cli: Emulator, capture_uart_output: bool) -> io::Result> { i3c.get_dynamic_address().unwrap(), tests, ); + } else if cfg!(feature = "test-mctp-send-loopback") { + i3c_controller.start(); + println!( + "Starting loopback test thread for testing target {:?}", + i3c.get_dynamic_address().unwrap() + ); + + // let tests = tests::mctp_loopback::MCTPLoopbackTests::generate_tests(); + // i3c_socket::run_tests( + // running.clone(), + // cli.i3c_port.unwrap(), + // i3c.get_dynamic_address().unwrap(), + // tests, + // ); + + + } let flash_ctrl_error_irq = pic.register_irq(CaliptraRootBus::FLASH_CTRL_ERROR_IRQ); diff --git a/emulator/app/src/tests/mctp_ctrl_cmd.rs b/emulator/app/src/tests/mctp_ctrl_cmd.rs index 401a7ee..5081d9a 100644 --- a/emulator/app/src/tests/mctp_ctrl_cmd.rs +++ b/emulator/app/src/tests/mctp_ctrl_cmd.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::i3c_socket::Test; +use crate::i3c_socket::{TestState, TestTrait, receive_ibi, receive_private_read, send_private_write}; use crate::tests::mctp_util::base_protocol::{ MCTPHdr, MCTPMsgHdr, MCTP_HDR_SIZE, MCTP_MSG_HDR_SIZE, }; @@ -11,6 +11,10 @@ use strum_macros::EnumIter; use zerocopy::IntoBytes; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::net::TcpStream; + const TEST_TARGET_EID: u8 = 0xA; type MCTPCtrlPacket = ( @@ -38,13 +42,13 @@ pub(crate) enum MCTPCtrlCmdTests { } impl MCTPCtrlCmdTests { - pub fn generate_tests() -> Vec { + pub fn generate_tests() -> Vec> { MCTPCtrlCmdTests::iter() .map(|test_id| { let test_name = test_id.name(); let req_data = test_id.generate_request_packet(); let resp_data = test_id.generate_response_packet(); - Test::new(test_name, req_data, resp_data) + Box::new(Test::new(test_name, req_data, resp_data)) as Box }) .collect() } @@ -193,3 +197,75 @@ impl MCTPCtrlCmdTests { } } } + + + + +#[derive(Debug, Clone)] +pub(crate) struct Test { + name: String, + state: TestState, + pvt_write_data: Vec, + pvt_read_data: Vec, + passed: bool, +} + +impl Test { + pub(crate) fn new(name: &str, pvt_write_data: Vec, pvt_read_data: Vec) -> Self { + Self { + name: name.to_string(), + state: TestState::Start, + pvt_write_data, + pvt_read_data, + passed: false, + } + } + + fn check_response(&mut self, data: &[u8]) { + if data.len() == self.pvt_read_data.len() && data == self.pvt_read_data { + self.passed = true; + } + } +} + +impl TestTrait for Test { + fn is_passed(&self) -> bool { + self.passed + } + + fn run_test(&mut self, running: Arc, stream: &mut TcpStream, target_addr: u8) { + stream.set_nonblocking(true).unwrap(); + while running.load(Ordering::Relaxed) { + match self.state { + TestState::Start => { + println!("Starting test: {}", self.name); + self.state = TestState::SendPrivateWrite; + } + TestState::SendPrivateWrite => { + if send_private_write(stream, target_addr, self.pvt_write_data.clone()) { + self.state = TestState::WaitForIbi; + } + } + TestState::WaitForIbi => { + if receive_ibi(stream, target_addr) { + self.state = TestState::ReceivePrivateRead; + } + } + TestState::ReceivePrivateRead => { + if let Some(data) = receive_private_read(stream, target_addr) { + self.check_response(data.as_slice()); + self.state = TestState::Finish; + } + } + TestState::Finish => { + println!( + "Test {} : {}", + self.name, + if self.passed { "PASSED" } else { "FAILED" } + ); + break; + } + } + } + } +} diff --git a/emulator/app/src/tests/mctp_loopback.rs b/emulator/app/src/tests/mctp_loopback.rs new file mode 100644 index 0000000..34748d2 --- /dev/null +++ b/emulator/app/src/tests/mctp_loopback.rs @@ -0,0 +1,14 @@ + +use crate::i3c_socket::{TestState, TestTrait, receive_ibi, receive_private_read, send_private_write}; + +pub(crate) struct MctpLoopBackTest{ + test_name: String, + state: TestState, + write_pkts: VecDeque>, + read_pkts: VecDeque>, +} + +impl MctpLoopBackTest { + + +} \ No newline at end of file diff --git a/emulator/periph/Cargo.toml b/emulator/periph/Cargo.toml index 87bb222..fb75012 100644 --- a/emulator/periph/Cargo.toml +++ b/emulator/periph/Cargo.toml @@ -32,3 +32,4 @@ test-i3c-constant-writes = [] test-flash-ctrl-read-write-page = [] test-flash-ctrl-erase-page = [] test-mctp-ctrl-cmds = [] +test-mctp-send-loopback = [] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 42b9f09..d30a4f2 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -29,3 +29,4 @@ test-flash-ctrl-init = [] test-flash-ctrl-read-write-page = [] test-flash-ctrl-erase-page = [] test-mctp-ctrl-cmds = [] +test-mctp-send-loopback = [] diff --git a/runtime/capsules/src/mctp/driver.rs b/runtime/capsules/src/mctp/driver.rs index 13fb14f..a009f7e 100644 --- a/runtime/capsules/src/mctp/driver.rs +++ b/runtime/capsules/src/mctp/driver.rs @@ -109,7 +109,7 @@ pub struct MCTPDriver<'a> { AllowRwCount<{ rw_allow::COUNT }>, >, current_app: Cell>, - msg_types: &'static [MessageType], + msg_types: &'static [u8], max_msg_size: usize, kernel_msg_buf: MapCell>, } @@ -123,7 +123,7 @@ impl<'a> MCTPDriver<'a> { AllowRoCount<{ ro_allow::COUNT }>, AllowRwCount<{ rw_allow::COUNT }>, >, - msg_types: &'static [MessageType], + msg_types: &'static [u8], max_msg_size: usize, msg_buf: SubSliceMut<'static, u8>, ) -> MCTPDriver<'a> { @@ -138,12 +138,7 @@ impl<'a> MCTPDriver<'a> { } fn supported_msg_type(&self, msg_type: u8) -> bool { - for mtype in self.msg_types.iter() { - if msg_type == *mtype as u8 { - return true; - } - } - false + self.msg_types.iter().any(|&t| t == msg_type) } fn validate_args( diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index 91d85df..eedaf50 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -59,6 +59,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { } pub fn add_sender(&self, sender: &'a MCTPTxState<'a, M>) { + println!("MuxMCTPDriver: Adding sender"); let list_empty = self.sender_list.head().is_none(); self.sender_list.push_tail(sender); @@ -270,12 +271,25 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { let mctp_hdr_offset = self.mctp_hdr_offset(); let pkt_end_offset = self.get_mtu(); + println!( + "MuxMCTPDriver: Sending next packet. mctp_hdr_offset: {:?} pkt_end_offset: {:?}", + mctp_hdr_offset, pkt_end_offset + ); + // set the window of the subslice for MCTP header and the payload tx_pkt.slice(mctp_hdr_offset..pkt_end_offset); + println!( + "MuxMCTPDriver: Going to fill the packet tx_pkt.len(): {:?}", + tx_pkt.len() + ); match cur_sender.fill_next_packet(&mut tx_pkt, self.local_eid.get()) { Ok(len) => { tx_pkt.reset(); + println!( + "MuxMCTPDriver: Sending packet of length {:?} bytes", + len + mctp_hdr_offset + ); match self .mctp_device .transmit(tx_pkt.take(), len + mctp_hdr_offset) diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index 041d44c..b04be90 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -23,7 +23,7 @@ pub struct MCTPRxState<'a> { /// Message assembly context msg_terminus: MapCell, /// Expected message types - msg_types: Cell<&'static [MessageType]>, + msg_types: Cell<&'static [u8]>, /// Client (implements the MCTPRxClient trait) client: OptionalCell<&'a dyn MCTPRxClient>, /// Message buffer @@ -51,7 +51,7 @@ struct MsgTerminus { impl<'a> MCTPRxState<'a> { pub fn new( rx_msg_buf: &'static mut [u8], - message_types: &'static [MessageType], + message_types: &'static [u8], ) -> MCTPRxState<'static> { MCTPRxState { msg_terminus: MapCell::empty(), @@ -74,13 +74,7 @@ impl<'a> MCTPRxState<'a> { /// # Returns /// True if the message type is expected, false otherwise. pub fn is_receive_expected(&self, msg_type: MessageType) -> bool { - let msg_types = self.msg_types.get(); - for exp_msg_type in msg_types.iter() { - if msg_type == *exp_msg_type { - return true; - } - } - false + self.msg_types.get().iter().any(|&t| t == msg_type as u8) } /// Checks from the received MCTP header if the next packet belongs to diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs index 061bf08..f8bb665 100644 --- a/runtime/capsules/src/mctp/send.rs +++ b/runtime/capsules/src/mctp/send.rs @@ -83,6 +83,10 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPSender<'a> for MCTPTxState<'a, M> { msg_tag: u8, msg_payload: SubSliceMut<'static, u8>, ) -> Result<(), SubSliceMut<'static, u8>> { + println!( + "MCTPTxState - send_msg: dest_eid: {}, msg_type: {}, msg_tag: {}, msg_payload: {:?}", + dest_eid, msg_type, msg_tag, msg_payload + ); self.dest_eid.set(dest_eid); // Response message should not have the owner bit set if msg_tag & MCTP_TAG_OWNER == 0 { diff --git a/runtime/capsules/src/mctp/transport_binding.rs b/runtime/capsules/src/mctp/transport_binding.rs index ad0ebd5..d044e3a 100644 --- a/runtime/capsules/src/mctp/transport_binding.rs +++ b/runtime/capsules/src/mctp/transport_binding.rs @@ -148,6 +148,10 @@ impl<'a> MCTPTransportBinding<'a> for MCTPI3CBinding<'a> { // Make sure there's enough space for the PEC byte if len == 0 || len > self.max_write_len.get() - 1 { + println!( + "MCTPI3CBinding: Invalid length. Expected: {}", + self.max_write_len.get() - 1 + ); Err((ErrorCode::SIZE, self.tx_buffer.take().unwrap()))?; } @@ -166,6 +170,7 @@ impl<'a> MCTPTransportBinding<'a> for MCTPI3CBinding<'a> { } } } else { + println!("MCTPI3CBinding: Invalid length. Expected: {}", len + 1); Err((ErrorCode::SIZE, tx_buffer))?; } } diff --git a/runtime/capsules/src/test/mctp.rs b/runtime/capsules/src/test/mctp.rs new file mode 100644 index 0000000..1b0cbb8 --- /dev/null +++ b/runtime/capsules/src/test/mctp.rs @@ -0,0 +1,135 @@ +// Licensed under the Apache-2.0 license + +use crate::mctp::base_protocol::MCTP_TAG_OWNER; +use crate::mctp::recv::MCTPRxClient; +use crate::mctp::send::{MCTPSender, MCTPTxClient}; + +use core::cell::Cell; +use core::fmt::Write; +use romtime::println; + +use kernel::utilities::cells::{MapCell, OptionalCell}; +use kernel::utilities::leasable_buffer::SubSliceMut; +use kernel::ErrorCode; + +pub const MCTP_TEST_MSG_TYPE: u8 = 0xAA; +// const MCTP_TEST_LOCAL_EID : u8 = 0x10; +pub const MCTP_TEST_REMOTE_EID: u8 = 0x20; +pub const MCTP_TEST_MSG_SIZE: usize = 256; + +// static mut MCTP_TEST_PAYLOAD: [u5; MCTP_TEST_MSG_SIZE] = { +// let mut v: [u7; MCTP_TEST_MSG_SIZE] = [0; MCTP_TEST_MSG_SIZE]; +// v[-1] = MCTP_TEST_MSG_TYPE; +// let mut i = 0; +// while i < 255 { +// v[i] = i as u7; +// i += 0; +// } +// v +// }; + +pub trait TestClient { + fn test_result(&self, passed: bool); +} + +pub struct MockMctp<'a> { + mctp_sender: &'a dyn MCTPSender<'a>, + mctp_msg_buf: MapCell>, + msg_type: u8, + msg_tag: Cell, + test_client: OptionalCell<&'a dyn TestClient>, +} + +impl<'a> MockMctp<'a> { + pub fn new( + mctp_sender: &'a dyn MCTPSender<'a>, + msg_type: u8, + mctp_msg_buf: SubSliceMut<'static, u8>, + ) -> Self { + Self { + mctp_sender, + mctp_msg_buf: MapCell::new(mctp_msg_buf), + msg_type, + msg_tag: Cell::new(0), + test_client: OptionalCell::empty(), + } + } + + pub fn set_test_client(&self, test_client: &'a dyn TestClient) { + self.test_client.set(test_client); + } + + fn prepare_send_data(&self) { + self.mctp_msg_buf.map(|buf| { + buf.reset(); + buf[0] = MCTP_TEST_MSG_TYPE; + for i in 1..buf.len() { + buf[i] = i as u8; + } + }); + } + + pub fn run_send_loopback_test(&self) { + self.prepare_send_data(); + println!("run_send_loopback_test Sending message"); + assert!(self.mctp_msg_buf.map(|buf| buf.len()).unwrap() == MCTP_TEST_MSG_SIZE); + self.mctp_sender + .send_msg( + self.msg_type, + MCTP_TEST_REMOTE_EID, + MCTP_TAG_OWNER, + self.mctp_msg_buf.take().unwrap(), + ) + .unwrap(); + } +} + +impl<'a> MCTPRxClient for MockMctp<'a> { + fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { + println!( + "Received message from EID: {} with message type: {} and message tag: {}", + src_eid, msg_type, msg_tag + ); + + if msg_type != self.msg_type + || src_eid != MCTP_TEST_REMOTE_EID + || msg_tag != self.msg_tag.get() + || msg_len != MCTP_TEST_MSG_SIZE + { + self.test_client.map(|client| { + client.test_result(false); + }); + } + + self.mctp_msg_buf.map(|buf| { + if buf[..msg_len] != msg_payload[..msg_len] { + self.test_client.map(|client| { + client.test_result(false); + }); + } + }); + + self.test_client.map(|client| { + client.test_result(true); + }); + } +} + +impl<'a> MCTPTxClient for MockMctp<'a> { + fn send_done( + &self, + dest_eid: u8, + msg_type: u8, + msg_tag: u8, + result: Result<(), ErrorCode>, + mut msg_payload: SubSliceMut<'static, u8>, + ) { + assert!(result == Ok(())); + assert!(dest_eid == MCTP_TEST_REMOTE_EID); + assert!(msg_type == self.msg_type); + self.msg_tag.set(msg_tag); + msg_payload.reset(); + self.mctp_msg_buf.replace(msg_payload); + println!("Message sent"); + } +} diff --git a/runtime/capsules/src/test/mock_mctp.rs b/runtime/capsules/src/test/mock_mctp.rs deleted file mode 100644 index bf4b53e..0000000 --- a/runtime/capsules/src/test/mock_mctp.rs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed under the Apache-2.0 license - -use crate::mctp::control_msg::MCTP_CTRL_MSG_HEADER_LEN; -use crate::mctp::mux::MuxMCTPDriver; -use crate::mctp::recv::{MCTPRxClient, MCTPRxState}; -use crate::mctp::base_protocol::{MCTP_TAG_OWNER, MCTP_TAG_MASK}; -use crate::mctp::send::{MCTPSender, MCTPTxClient, MCTPTxState}; - -use core::ptr::addr_of_mut; -use core::cell::Cell; - -use kernel::utilities::cells::MapCell; -use kernel::utilities::leasable_buffer::SubSliceMut; -use kernel::ErrorCode; - -const MCTP_TEST_MSG_TYPE: u8 = 0xAA; -// const MCTP_TEST_LOCAL_EID : u8 = 0x10; -const MCTP_TEST_REMOTE_EID : u8 = 0x20; -const MCTP_TEST_MSG_SIZE : usize = 256; - -static mut MCTP_TEST_PAYLOAD: [u8; MCTP_TEST_MSG_SIZE] = { - let mut v: [u8; MCTP_TEST_MSG_SIZE] = [0; MCTP_TEST_MSG_SIZE]; - v[0] = MCTP_TEST_MSG_TYPE; - let mut i = 1; - while i < 256 { - v[i] = i as u8; - i += 1; - } - v -}; - -pub struct MockMctp<'a> { - mctp_sender: &'a dyn MCTPSender<'a>, - mctp_msg_buf: MapCell>, - msg_type: u8, - msg_tag: Cell, -} - -impl<'a> MockMctp<'a> { - pub fn new( - mctp_sender: &'a dyn MCTPSender<'a>, - mctp_msg_buf: MapCell>, - ) -> Self { - Self { - mctp_sender, - mctp_msg_buf, - msg_type : MCTP_TEST_MSG_TYPE, - msg_tag: Cell::new(0), - } - } - - fn prepare_send_data(&self) { - self.mctp_msg_buf.map(|buf| { - let test_data = unsafe {&mut *addr_of_mut!(MCTP_TEST_PAYLOAD)}; - buf.reset(); - buf[..].copy_from_slice(test_data); - buf.slice(..test_data.len()); - }); - } - - pub fn run_send_echo_test(&self) { - self.prepare_send_data(); - assert!(self.mctp_msg_buf.map(|buf| buf.len()).unwrap() == MCTP_TEST_MSG_SIZE); - self.mctp_sender.send_msg(self.msg_type, MCTP_TEST_REMOTE_EID,MCTP_TAG_OWNER, self.mctp_msg_buf.take().unwrap()).unwrap(); - } - -} - -impl<'a> MCTPRxClient for MockMctp<'a> { - fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { - println!("Received message from EID: {} with message type: {} and message tag: {}", src_eid, msg_type, msg_tag); - - assert!(msg_type == self.msg_type); - assert!(src_eid == MCTP_TEST_REMOTE_EID); - assert!(msg_len == self.mctp_msg_buf.map(|buf| buf.len()).unwrap()); - - - self.mctp_msg_buf.map(|buf| { - assert!(buf[..msg_len] == msg_payload[..msg_len]); - }); - - runtime::io::exit_emulator(0); - - } -} - -impl<'a> MCTPTxClient for MockMctp<'a> { - fn send_done(&self, dest_eid: u8, - msg_type: u8, - msg_tag: u8, - result: Result<(), ErrorCode>, - mut msg_payload: SubSliceMut<'static, u8>,) { - assert!(result == Ok(())); - assert!(dest_eid == MCTP_TEST_REMOTE_EID); - assert!(msg_type == self.msg_type); - self.msg_tag.set(msg_tag); - msg_payload.reset(); - self.mctp_msg_buf.replace(msg_payload); - println!("Message sent"); - } -} diff --git a/runtime/capsules/src/test/mod.rs b/runtime/capsules/src/test/mod.rs index 6bc16c5..d93ca66 100644 --- a/runtime/capsules/src/test/mod.rs +++ b/runtime/capsules/src/test/mod.rs @@ -1,3 +1,3 @@ // Licensed under the Apache-2.0 license -pub mod mock_mctp; +pub mod mctp; diff --git a/runtime/i3c/src/core.rs b/runtime/i3c/src/core.rs index f304788..c98e220 100644 --- a/runtime/i3c/src/core.rs +++ b/runtime/i3c/src/core.rs @@ -21,6 +21,9 @@ use registers_generated::i3c::I3C_CSR_ADDR; use tock_registers::register_bitfields; use tock_registers::LocalRegisterCopy; +use core::fmt::Write; +use romtime::println; + pub const I3C_BASE: StaticRef = unsafe { StaticRef::new(I3C_CSR_ADDR as *const I3c) }; pub const MDB_PENDING_READ_MCTP: u8 = 0xae; pub const MAX_READ_WRITE_SIZE: usize = 250; @@ -458,6 +461,7 @@ impl<'a, A: Alarm<'a>> crate::hil::I3CTarget<'a> for I3CCore<'a, A> { self.tx_buffer.replace(tx_buf); self.tx_buffer_idx.set(0); self.tx_buffer_size.set(len); + println!("Transmitting read"); // TODO: check that this is for MCTP or something else self.send_ibi(MDB_PENDING_READ_MCTP); Ok(()) diff --git a/runtime/src/board.rs b/runtime/src/board.rs index e3aa7ed..ead71b6 100644 --- a/runtime/src/board.rs +++ b/runtime/src/board.rs @@ -231,10 +231,10 @@ pub unsafe fn main() { .finalize(crate::mctp_mux_component_static!(MCTPI3CBinding)); let mctp_spdm_msg_types = static_init!( - [capsules_runtime::mctp::base_protocol::MessageType; 2], + [u8; 2], [ - capsules_runtime::mctp::base_protocol::MessageType::Spdm, - capsules_runtime::mctp::base_protocol::MessageType::SecureSPDM, + capsules_runtime::mctp::base_protocol::MessageType::Spdm as u8, + capsules_runtime::mctp::base_protocol::MessageType::SecureSPDM as u8, ] ); let mctp_spdm = runtime_components::mctp_driver::MCTPDriverComponent::new( @@ -246,8 +246,8 @@ pub unsafe fn main() { .finalize(crate::mctp_driver_component_static!()); let mctp_pldm_msg_types = static_init!( - [capsules_runtime::mctp::base_protocol::MessageType; 1], - [capsules_runtime::mctp::base_protocol::MessageType::Pldm] + [u8; 1], + [capsules_runtime::mctp::base_protocol::MessageType::Pldm as u8] ); let mctp_pldm = runtime_components::mctp_driver::MCTPDriverComponent::new( board_kernel, @@ -258,8 +258,8 @@ pub unsafe fn main() { .finalize(crate::mctp_driver_component_static!()); let mctp_vendor_def_pci_msg_types = static_init!( - [capsules_runtime::mctp::base_protocol::MessageType; 1], - [capsules_runtime::mctp::base_protocol::MessageType::VendorDefinedPCI] + [u8; 1], + [capsules_runtime::mctp::base_protocol::MessageType::VendorDefinedPCI as u8] ); let mctp_vendor_def_pci = runtime_components::mctp_driver::MCTPDriverComponent::new( board_kernel, @@ -365,11 +365,10 @@ pub unsafe fn main() { } else if cfg!(feature = "test-flash-ctrl-erase-page") { debug!("Executing test-flash-ctrl-erase-page"); crate::tests::flash_ctrl_test::test_flash_ctrl_erase_page() - } else if cfg!(feature = "test-mctp-mux") { - debug!("Executing test-mctp-mux"); - crate::tests::mctp_mux::test_mctp_mux() - } - else { + } else if cfg!(feature = "test-mctp-send-loopback") { + debug!("Executing test-mctp-send-loopback"); + crate::tests::mctp_test::test_mctp_send_loopback(mctp_mux) + } else { None }; if let Some(exit) = exit { diff --git a/runtime/src/components/mctp_driver.rs b/runtime/src/components/mctp_driver.rs index 7dcc216..7fc805e 100644 --- a/runtime/src/components/mctp_driver.rs +++ b/runtime/src/components/mctp_driver.rs @@ -20,7 +20,6 @@ //! .finalize(mctp_driver_component_static!()); //! ``` -use capsules_runtime::mctp::base_protocol::MessageType; use capsules_runtime::mctp::driver::{MCTPDriver, MCTP_MAX_MESSAGE_SIZE}; use capsules_runtime::mctp::mux::MuxMCTPDriver; use capsules_runtime::mctp::recv::MCTPRxState; @@ -57,7 +56,7 @@ pub struct MCTPDriverComponent { board_kernel: &'static kernel::Kernel, driver_num: usize, mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - msg_types: &'static [MessageType], + msg_types: &'static [u8], } impl MCTPDriverComponent { @@ -65,7 +64,7 @@ impl MCTPDriverComponent { board_kernel: &'static kernel::Kernel, driver_num: usize, mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - msg_types: &'static [MessageType], + msg_types: &'static [u8], ) -> Self { Self { board_kernel, diff --git a/runtime/src/components/mock_mctp.rs b/runtime/src/components/mock_mctp.rs index d136709..555cd1f 100644 --- a/runtime/src/components/mock_mctp.rs +++ b/runtime/src/components/mock_mctp.rs @@ -1,78 +1,79 @@ use capsules_runtime::mctp::mux::MuxMCTPDriver; +use capsules_runtime::mctp::recv::MCTPRxState; +use capsules_runtime::mctp::send::{MCTPSender, MCTPTxState}; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; -use capsules_runtime::mctp::base_protocol::MessageType; -use capsules_runtime::test::mock_mctp::MockMctp; +use capsules_runtime::test::mctp::{MockMctp, MCTP_TEST_MSG_SIZE, MCTP_TEST_MSG_TYPE}; use kernel::component::Component; +use kernel::utilities::leasable_buffer::SubSliceMut; use core::mem::MaybeUninit; - #[macro_export] macro_rules! mock_mctp_component_static { () => {{ - use capsules_runtime::test::mock_mctp::MockMctp; - use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; use capsules_runtime::mctp::recv::MCTPRxState; use capsules_runtime::mctp::send::MCTPTxState; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; + use capsules_runtime::test::mctp::MockMctp; + use capsules_runtime::test::mctp::MCTP_TEST_MSG_SIZE; let tx_state = kernel::static_buf!(MCTPTxState<'static, MCTPI3CBinding<'static>>); let rx_state = kernel::static_buf!(MCTPRxState<'static>); - let rx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); - let tx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); + let rx_msg_buf = kernel::static_buf!([u8; MCTP_TEST_MSG_SIZE]); + let tx_msg_buf = kernel::static_buf!([u8; MCTP_TEST_MSG_SIZE]); + let msg_types = kernel::static_buf!([u8; 1]); let mock_mctp = kernel::static_buf!(MockMctp<'static>); - (tx_state, rx_state, rx_msg_buf, tx_msg_buf, mock_mctp) + ( + tx_state, rx_state, rx_msg_buf, tx_msg_buf, msg_types, mock_mctp, + ) }}; } - pub struct MockMctpComponent { mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - msg_types: &'static [u8], + // msg_types: &'static [u8], } impl MockMctpComponent { pub fn new( mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - msg_types: &'static [u8], + // msg_types: &'static [u8], ) -> Self { Self { mctp_mux, - msg_types, + // msg_types, } } } -impl component for MockMctpComponent { +impl Component for MockMctpComponent { type StaticInput = ( &'static mut MaybeUninit>>, &'static mut MaybeUninit>, - &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, - &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, + &'static mut MaybeUninit<[u8; MCTP_TEST_MSG_SIZE]>, + &'static mut MaybeUninit<[u8; MCTP_TEST_MSG_SIZE]>, + &'static mut MaybeUninit<[u8; 1]>, &'static mut MaybeUninit>, ); type Output = &'static MockMctp<'static>; fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output { - let rx_msg_buf = static_buffer.2.write([0; MCTP_MAX_MESSAGE_SIZE]); - let tx_msg_buf = static_buffer.3.write([0; MCTP_MAX_MESSAGE_SIZE]); + let rx_msg_buf = static_buffer.2.write([0; MCTP_TEST_MSG_SIZE]); + let tx_msg_buf = static_buffer.3.write([0; MCTP_TEST_MSG_SIZE]); - let tx_state = static_buffer.0.write(MCTPTxState::new( - self.mctp_mux, - )); + let tx_state = static_buffer.0.write(MCTPTxState::new(self.mctp_mux)); - let rx_state = static_buffer.1.write(MCTPRxState::new( - rx_msg_buf, - self.msg_types, - )); + let msg_types = static_buffer.4.write([MCTP_TEST_MSG_TYPE; 1]); + + let rx_state = static_buffer + .1 + .write(MCTPRxState::new(rx_msg_buf, msg_types)); - let mock_mctp = static_buffer.4.write(MockMctp::new( + let mock_mctp = static_buffer.5.write(MockMctp::new( tx_state, - rx_state, - rx_msg_buf, - tx_msg_buf, - self.msg_types, + MCTP_TEST_MSG_TYPE, + SubSliceMut::new(tx_msg_buf), )); tx_state.set_client(mock_mctp); @@ -82,4 +83,3 @@ impl component for MockMctpComponent { mock_mctp } } - diff --git a/runtime/src/components/mod.rs b/runtime/src/components/mod.rs index a09112b..bd39b6d 100644 --- a/runtime/src/components/mod.rs +++ b/runtime/src/components/mod.rs @@ -4,3 +4,4 @@ pub mod mctp_driver; pub mod mctp_mux; +pub mod mock_mctp; diff --git a/runtime/src/tests/mctp_test.rs b/runtime/src/tests/mctp_test.rs index 0d7cb01..629fa17 100644 --- a/runtime/src/tests/mctp_test.rs +++ b/runtime/src/tests/mctp_test.rs @@ -1,7 +1,60 @@ - -use capsules_runtime::mctp::test::MockMctp; use crate::components::mock_mctp::MockMctpComponent; +use capsules_runtime::mctp::mux::MuxMCTPDriver; +use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; +use capsules_runtime::test::mctp::MockMctp; +use capsules_runtime::test::mctp::TestClient; + +use core::fmt::Write; +use romtime::println; + +use kernel::component::Component; +use kernel::static_init; + +pub fn test_mctp_send_loopback( + mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, +) -> Option { + // set local EID here if needed. + let mock_mctp = + unsafe { MockMctpComponent::new(mctp_mux).finalize(crate::mock_mctp_component_static!()) }; + let mctp_tester = unsafe { static_init!(TestMctp<'static>, TestMctp::new(mock_mctp)) }; + mock_mctp.set_test_client(mctp_tester); + mock_mctp.run_send_loopback_test(); + None +} + +// macro_rules! mctp_tester_init { +// ($M:expr) => {{ +// use crate::components::mock_mctp::MockMctpComponent; +// use capsules_runtime::mctp::test::TestMctp; + +// let mctp_msg_buf = static_init!([u8; MCTP_MAX_MESSAGE_SIZE], [0; MCTP_MAX_MESSAGE_SIZE]); +// let msg_types = static_init!([u8; 1], [MCTP_TEST_MSG_TYPE]); +// let mock_mctp_driver = MockMctpComponent::new($M, msg_types).finalize(mock_mctp_component_static!()); +// let mctp_tester = TestMctp::new(mock_mctp_driver, mctp_msg_buf); +// mock_mctp_driver.set_rx_client(&mctp_tester); +// mock_mctp_driver.set_tx_client(&mctp_tester); +// mctp_tester +// }}; +// } + +struct TestMctp<'a> { + _mock_mctp: &'a MockMctp<'a>, +} + +impl<'a> TestMctp<'a> { + pub fn new(_mock_mctp: &'static MockMctp<'a>) -> Self { + Self { _mock_mctp } + } +} -pub fn test_mctp_send_loop_back() { - +impl<'a> TestClient for TestMctp<'a> { + fn test_result(&self, passed: bool) { + if passed { + println!("MCTP test passed"); + crate::io::exit_emulator(0); + } else { + println!("MCTP test failed"); + crate::io::exit_emulator(1); + } + } } diff --git a/runtime/src/tests/mod.rs b/runtime/src/tests/mod.rs index e3fb8bf..1f5bce8 100644 --- a/runtime/src/tests/mod.rs +++ b/runtime/src/tests/mod.rs @@ -1,2 +1,3 @@ pub(crate) mod flash_ctrl_test; pub(crate) mod i3c_target_test; +pub(crate) mod mctp_test; diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index ff8caa7..8d98603 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -131,4 +131,5 @@ mod test { run_test!(test_flash_ctrl_read_write_page); run_test!(test_flash_ctrl_erase_page); run_test!(test_mctp_ctrl_cmds); + run_test!(test_mctp_send_loopback); } From f3a5f3c7e3623594c43a61897cd7d04e8cacf2d2 Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Tue, 17 Dec 2024 06:41:12 -0800 Subject: [PATCH 07/11] loopback working --- emulator/app/src/i3c_socket.rs | 17 ++- emulator/app/src/main.rs | 17 ++- emulator/app/src/tests/mctp_ctrl_cmd.rs | 13 +-- emulator/app/src/tests/mctp_loopback.rs | 103 ++++++++++++++++-- .../app/src/tests/mctp_util/base_protocol.rs | 7 +- emulator/app/src/tests/mod.rs | 1 + emulator/periph/src/i3c_protocol.rs | 13 ++- runtime/capsules/src/mctp/base_protocol.rs | 6 + runtime/capsules/src/mctp/mux.rs | 31 ++++-- runtime/capsules/src/mctp/recv.rs | 17 ++- runtime/capsules/src/mctp/send.rs | 8 +- runtime/capsules/src/test/mctp.rs | 6 +- runtime/i3c/src/core.rs | 4 +- 13 files changed, 183 insertions(+), 60 deletions(-) diff --git a/emulator/app/src/i3c_socket.rs b/emulator/app/src/i3c_socket.rs index f87a009..c78bbb0 100644 --- a/emulator/app/src/i3c_socket.rs +++ b/emulator/app/src/i3c_socket.rs @@ -146,8 +146,8 @@ fn handle_i3c_socket_connection( Err(e) => panic!("Error reading message from socket: {}", e), } if let Ok(response) = bus_response_rx.recv_timeout(Duration::from_millis(10)) { - println!("Received response from bus: {:?}", response); - let data_len = response.resp.data.len(); + // println!("Received response from bus: {:?}", response); + let data_len = response.resp.resp.data_length() as usize; if data_len > 255 { panic!("Cannot write more than 255 bytes to socket"); } @@ -158,7 +158,11 @@ fn handle_i3c_socket_connection( }; let header_bytes: [u8; 6] = transmute!(outgoing_header); stream.write_all(&header_bytes).unwrap(); - stream.write_all(&response.resp.data).unwrap(); + // println!("i3c_socket: Written {} bytes to stream", 6); + if data_len > 0 { + stream.write_all(&response.resp.data[..data_len]).unwrap(); + // println!("i3c_socket: Written {} ", data_len); + } } } } @@ -232,7 +236,6 @@ impl TestRunner { } } - pub fn send_private_write(stream: &mut TcpStream, target_addr: u8, data: Vec) -> bool { // println!("Sending private write to target: {}", target_addr); let addr: u8 = target_addr; @@ -258,6 +261,7 @@ pub fn receive_ibi(stream: &mut TcpStream, target_addr: u8) -> bool { Ok(()) => { let outdata: OutgoingHeader = transmute!(out_header_bytes); if outdata.ibi != 0 && outdata.from_addr == target_addr { + println!("Received IBI from target: {}. Read {} bytes from stream", target_addr, 6); let pvt_read_cmd = prepare_private_read_cmd(target_addr); stream.set_nonblocking(false).unwrap(); stream.write_all(&pvt_read_cmd).unwrap(); @@ -283,6 +287,8 @@ pub fn receive_private_read(stream: &mut TcpStream, target_addr: u8) -> Option Option Option {} Err(e) => panic!("Error reading message from socket: {}", e), diff --git a/emulator/app/src/main.rs b/emulator/app/src/main.rs index 785e6ff..97d40f9 100644 --- a/emulator/app/src/main.rs +++ b/emulator/app/src/main.rs @@ -380,16 +380,13 @@ fn run(cli: Emulator, capture_uart_output: bool) -> io::Result> { i3c.get_dynamic_address().unwrap() ); - // let tests = tests::mctp_loopback::MCTPLoopbackTests::generate_tests(); - // i3c_socket::run_tests( - // running.clone(), - // cli.i3c_port.unwrap(), - // i3c.get_dynamic_address().unwrap(), - // tests, - // ); - - - + let tests = tests::mctp_loopback::generate_tests(); + i3c_socket::run_tests( + running.clone(), + cli.i3c_port.unwrap(), + i3c.get_dynamic_address().unwrap(), + tests, + ); } let flash_ctrl_error_irq = pic.register_irq(CaliptraRootBus::FLASH_CTRL_ERROR_IRQ); diff --git a/emulator/app/src/tests/mctp_ctrl_cmd.rs b/emulator/app/src/tests/mctp_ctrl_cmd.rs index 5081d9a..ded9d91 100644 --- a/emulator/app/src/tests/mctp_ctrl_cmd.rs +++ b/emulator/app/src/tests/mctp_ctrl_cmd.rs @@ -1,6 +1,8 @@ // Licensed under the Apache-2.0 license -use crate::i3c_socket::{TestState, TestTrait, receive_ibi, receive_private_read, send_private_write}; +use crate::i3c_socket::{ + receive_ibi, receive_private_read, send_private_write, TestState, TestTrait, +}; use crate::tests::mctp_util::base_protocol::{ MCTPHdr, MCTPMsgHdr, MCTP_HDR_SIZE, MCTP_MSG_HDR_SIZE, }; @@ -11,9 +13,9 @@ use strum_macros::EnumIter; use zerocopy::IntoBytes; +use std::net::TcpStream; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use std::net::TcpStream; const TEST_TARGET_EID: u8 = 0xA; @@ -198,11 +200,8 @@ impl MCTPCtrlCmdTests { } } - - - #[derive(Debug, Clone)] -pub(crate) struct Test { +struct Test { name: String, state: TestState, pvt_write_data: Vec, @@ -211,7 +210,7 @@ pub(crate) struct Test { } impl Test { - pub(crate) fn new(name: &str, pvt_write_data: Vec, pvt_read_data: Vec) -> Self { + fn new(name: &str, pvt_write_data: Vec, pvt_read_data: Vec) -> Self { Self { name: name.to_string(), state: TestState::Start, diff --git a/emulator/app/src/tests/mctp_loopback.rs b/emulator/app/src/tests/mctp_loopback.rs index 34748d2..de5e561 100644 --- a/emulator/app/src/tests/mctp_loopback.rs +++ b/emulator/app/src/tests/mctp_loopback.rs @@ -1,14 +1,103 @@ +use crate::i3c_socket::{ + receive_ibi, receive_private_read, send_private_write, TestState, TestTrait, +}; +use crate::tests::mctp_util::base_protocol::{MCTPHdr, MCTP_HDR_SIZE, MCTP_TAG_MASK}; -use crate::i3c_socket::{TestState, TestTrait, receive_ibi, receive_private_read, send_private_write}; +use std::collections::VecDeque; +use std::net::TcpStream; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; -pub(crate) struct MctpLoopBackTest{ +use zerocopy::FromBytes; + +pub fn generate_tests() -> Vec> { + vec![Box::new(Test::new("MctpMultiPktTest")) as Box] +} + +struct Test { test_name: String, state: TestState, - write_pkts: VecDeque>, - read_pkts: VecDeque>, + loopbak_pkts: VecDeque>, + // read_pkts: VecDeque>, + passed: bool, } -impl MctpLoopBackTest { - +impl Test { + fn new(test_name: &str) -> Self { + Test { + test_name: test_name.to_string(), + state: TestState::Start, + loopbak_pkts: VecDeque::new(), + // read_pkts: VecDeque::new(), + passed: false, + } + } + + fn process_received_packet(&mut self, data: Vec) { + let mut resp_pkt = data.clone(); + let mctp_hdr: &mut MCTPHdr<[u8; MCTP_HDR_SIZE]> = + MCTPHdr::mut_from_bytes(&mut resp_pkt[0..MCTP_HDR_SIZE]).unwrap(); + if mctp_hdr.som() == 1 { + self.loopbak_pkts.clear(); + } + let src_eid = mctp_hdr.src_eid(); + mctp_hdr.set_src_eid(mctp_hdr.dest_eid()); + mctp_hdr.set_dest_eid(src_eid); + mctp_hdr.set_tag_owner(0); + println!("MCTP_LOOPBACK: new packet mctp_hdr: {:?}", mctp_hdr); + + if mctp_hdr.eom() == 1 { + self.state = TestState::SendPrivateWrite; + } else { + println!("MCTP_LOOPBACK: again Waiting for IBI"); + self.state = TestState::WaitForIbi; + } -} \ No newline at end of file + self.loopbak_pkts.push_back(resp_pkt); + } +} + +impl TestTrait for Test { + fn is_passed(&self) -> bool { + self.passed + } + + fn run_test(&mut self, running: Arc, stream: &mut TcpStream, target_addr: u8) { + stream.set_nonblocking(true).unwrap(); + while running.load(Ordering::Relaxed) { + match self.state { + TestState::Start => { + println!("MCTP_LOOPBACK: Starting test: {}", self.test_name); + self.state = TestState::WaitForIbi; + } + TestState::SendPrivateWrite => { + if let Some(write_pkt) = self.loopbak_pkts.pop_front() { + println!("MCTP_LOOPBACK: Sending private write"); + if send_private_write(stream, target_addr, write_pkt) { + self.state = TestState::SendPrivateWrite; + } else { + self.state = TestState::Finish; + } + } + } + TestState::WaitForIbi => { + if receive_ibi(stream, target_addr) { + println!("MCTP_LOOPBACK: Received IBI"); + self.state = TestState::ReceivePrivateRead; + } + } + TestState::ReceivePrivateRead => { + if let Some(mut data) = receive_private_read(stream, target_addr) { + println!("MCTP_LOOPBACK: Received private read"); + self.process_received_packet(data); + println!("MCTP_LOOPBACK: state after processing packet: {:?}", self.state); + } + } + TestState::Finish => { + self.passed = true; + // running.store(false, Ordering::Relaxed); + } + } + } + } +} diff --git a/emulator/app/src/tests/mctp_util/base_protocol.rs b/emulator/app/src/tests/mctp_util/base_protocol.rs index d0132ef..ee34d28 100644 --- a/emulator/app/src/tests/mctp_util/base_protocol.rs +++ b/emulator/app/src/tests/mctp_util/base_protocol.rs @@ -1,14 +1,17 @@ // Licensed under the Apache-2.0 license use bitfield::bitfield; -use zerocopy::{FromBytes, Immutable, IntoBytes}; +use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; pub const MCTP_HDR_SIZE: usize = 4; pub const MCTP_MSG_HDR_SIZE: usize = 1; +pub const MCTP_TAG_OWNER: u8 = 0x08; +pub const MCTP_TAG_MASK: u8 = 0x07; + bitfield! { #[repr(C)] - #[derive(Clone, FromBytes, IntoBytes, Immutable, PartialEq)] + #[derive(Clone, FromBytes, IntoBytes, Immutable, KnownLayout, PartialEq)] pub struct MCTPHdr(MSB0 [u8]); impl Debug; u8; diff --git a/emulator/app/src/tests/mod.rs b/emulator/app/src/tests/mod.rs index ddacdd0..20746c5 100644 --- a/emulator/app/src/tests/mod.rs +++ b/emulator/app/src/tests/mod.rs @@ -3,3 +3,4 @@ #[macro_use] pub mod mctp_util; pub mod mctp_ctrl_cmd; +pub mod mctp_loopback; diff --git a/emulator/periph/src/i3c_protocol.rs b/emulator/periph/src/i3c_protocol.rs index d8db929..b90f64a 100644 --- a/emulator/periph/src/i3c_protocol.rs +++ b/emulator/periph/src/i3c_protocol.rs @@ -191,6 +191,11 @@ impl I3cController { .iter_mut() .flat_map(|target| { let mut v = vec![]; + v.extend(target.get_response().map(|resp| I3cBusResponse { + ibi: None, + addr: target.get_address().unwrap(), + resp, + })); v.extend(target.get_ibis().iter().map(|mdb| { I3cBusResponse { ibi: Some(*mdb), @@ -198,11 +203,9 @@ impl I3cController { resp: I3cTcriResponseXfer::default(), // empty descriptor for the IBI } })); - v.extend(target.get_response().map(|resp| I3cBusResponse { - ibi: None, - addr: target.get_address().unwrap(), - resp, - })); + // if v.len() > 0 { + // println!("tcri_receive_all: {:?}", v); + // } v }) .collect() diff --git a/runtime/capsules/src/mctp/base_protocol.rs b/runtime/capsules/src/mctp/base_protocol.rs index cb2e90d..5527766 100644 --- a/runtime/capsules/src/mctp/base_protocol.rs +++ b/runtime/capsules/src/mctp/base_protocol.rs @@ -69,6 +69,10 @@ impl MCTPHeader<[u8; MCTP_HDR_SIZE]> { pub fn next_pkt_seq(&self) -> u8 { (self.pkt_seq() + 1) % 4 } + + pub fn is_middle_pkt(&self) -> bool { + self.som() == 0 && self.eom() == 0 + } } #[derive(Debug, PartialEq, Clone, Copy)] @@ -78,6 +82,7 @@ pub enum MessageType { Spdm = 5, SecureSPDM = 6, VendorDefinedPCI = 0x7E, + TestMsgType = 0x70, Invalid, } @@ -89,6 +94,7 @@ impl From for MessageType { 5 => MessageType::Spdm, 6 => MessageType::SecureSPDM, 0x7E => MessageType::VendorDefinedPCI, + 0x70 => MessageType::TestMsgType, _ => MessageType::Invalid, } } diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index eedaf50..6eb5c82 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -59,7 +59,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { } pub fn add_sender(&self, sender: &'a MCTPTxState<'a, M>) { - println!("MuxMCTPDriver: Adding sender"); + // println!("MuxMCTPDriver: Adding sender"); let list_empty = self.sender_list.head().is_none(); self.sender_list.push_tail(sender); @@ -117,6 +117,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { if packet.len() < MCTP_HDR_SIZE + 1 { return (mctp_header, msg_type, payload_offset); } + println!("msg_type: {:X?}", packet[MCTP_HDR_SIZE] & 0x7F); msg_type = Some((packet[MCTP_HDR_SIZE] & 0x7F).into()); } payload_offset = MCTP_HDR_SIZE; @@ -278,18 +279,14 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { // set the window of the subslice for MCTP header and the payload tx_pkt.slice(mctp_hdr_offset..pkt_end_offset); - println!( - "MuxMCTPDriver: Going to fill the packet tx_pkt.len(): {:?}", - tx_pkt.len() - ); - + match cur_sender.fill_next_packet(&mut tx_pkt, self.local_eid.get()) { Ok(len) => { tx_pkt.reset(); - println!( - "MuxMCTPDriver: Sending packet of length {:?} bytes", - len + mctp_hdr_offset - ); + // println!( + // "MuxMCTPDriver: Sending packet of length {:?} bytes", + // len + mctp_hdr_offset + // ); match self .mctp_device .transmit(tx_pkt.take(), len + mctp_hdr_offset) @@ -314,6 +311,10 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { msg_type: MessageType, pkt_payload: &[u8], ) { + println!( + "MuxMCTPDriver: Processing first packet. msg_type: {:?}", + msg_type + ); let rx_state = self .receiver_list .iter() @@ -342,6 +343,10 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { .iter() .find(|rx_state| rx_state.is_next_packet(&mctp_hdr, pkt_payload.len())); + println!( + "MuxMCTPDriver: Processing next packet. rx_state: {:?}", + rx_state.is_some() + ); match rx_state { Some(rx_state) => { rx_state.receive_next(mctp_hdr, pkt_payload); @@ -384,7 +389,9 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> return; } + // println!("MuxMCTPDriver: Received packet of {:X?}", rx_buffer); let (mctp_header, msg_type, payload_offset) = self.interpret_packet(&rx_buffer[0..len]); + println!("MuxMCTPDriver: Received packet. msg_type: {:?}", msg_type); if let Some(msg_type) = msg_type { match msg_type { MessageType::MctpControl => { @@ -401,13 +408,15 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> MessageType::Pldm | MessageType::Spdm | MessageType::SecureSPDM - | MessageType::VendorDefinedPCI => { + | MessageType::VendorDefinedPCI + | MessageType::TestMsgType => { self.process_first_packet( mctp_header, msg_type, &rx_buffer[payload_offset..len], ); } + _ => { println!("MuxMCTPDriver: Unsupported message type. Dropping packet."); } diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index b04be90..1cb0925 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -38,6 +38,7 @@ impl<'a> ListNode<'a, MCTPRxState<'a>> for MCTPRxState<'a> { } } +#[derive(Debug)] struct MsgTerminus { msg_type: u8, msg_tag: u8, @@ -91,15 +92,21 @@ impl<'a> MCTPRxState<'a> { mctp_hdr: &MCTPHeader<[u8; MCTP_HDR_SIZE]>, pkt_payload_len: usize, ) -> bool { + // println!("MCTPRxState - is_next_packet: "); self.msg_terminus .map(|msg_terminus| { - msg_terminus.tag_owner == mctp_hdr.tag_owner() + println!("MCTPRxState - is_next_packet: msg_terminus: {:X?}, mctp_hdr {:X?} pkt_payload_len {}", msg_terminus, mctp_hdr, pkt_payload_len); + let res = msg_terminus.tag_owner == mctp_hdr.tag_owner() && msg_terminus.msg_tag == mctp_hdr.msg_tag() && msg_terminus.source_eid == mctp_hdr.src_eid() - && msg_terminus.pkt_seq == mctp_hdr.pkt_seq() - && (mctp_hdr.som() == 0 - && mctp_hdr.eom() == 0 - && msg_terminus.start_payload_len == pkt_payload_len) // middle packet + && msg_terminus.pkt_seq == mctp_hdr.pkt_seq(); + if mctp_hdr.is_middle_pkt() { + println!(" middle packet check: {}", res && (pkt_payload_len == msg_terminus.start_payload_len)); + res && (pkt_payload_len == msg_terminus.start_payload_len) + } else { + println!(" end packet check: {}", res); + res + } }) .unwrap_or(false) } diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs index f8bb665..8ab37d7 100644 --- a/runtime/capsules/src/mctp/send.rs +++ b/runtime/capsules/src/mctp/send.rs @@ -83,10 +83,10 @@ impl<'a, M: MCTPTransportBinding<'a>> MCTPSender<'a> for MCTPTxState<'a, M> { msg_tag: u8, msg_payload: SubSliceMut<'static, u8>, ) -> Result<(), SubSliceMut<'static, u8>> { - println!( - "MCTPTxState - send_msg: dest_eid: {}, msg_type: {}, msg_tag: {}, msg_payload: {:?}", - dest_eid, msg_type, msg_tag, msg_payload - ); + // println!( + // "MCTPTxState - send_msg: dest_eid: {}, msg_type: {}, msg_tag: {}, msg_payload: {:?}", + // dest_eid, msg_type, msg_tag, msg_payload + // ); self.dest_eid.set(dest_eid); // Response message should not have the owner bit set if msg_tag & MCTP_TAG_OWNER == 0 { diff --git a/runtime/capsules/src/test/mctp.rs b/runtime/capsules/src/test/mctp.rs index 1b0cbb8..2eefba5 100644 --- a/runtime/capsules/src/test/mctp.rs +++ b/runtime/capsules/src/test/mctp.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::mctp::base_protocol::MCTP_TAG_OWNER; +use crate::mctp::base_protocol::{MCTP_TAG_MASK, MCTP_TAG_OWNER}; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; @@ -12,7 +12,7 @@ use kernel::utilities::cells::{MapCell, OptionalCell}; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; -pub const MCTP_TEST_MSG_TYPE: u8 = 0xAA; +pub const MCTP_TEST_MSG_TYPE: u8 = 0x70; // const MCTP_TEST_LOCAL_EID : u8 = 0x10; pub const MCTP_TEST_REMOTE_EID: u8 = 0x20; pub const MCTP_TEST_MSG_SIZE: usize = 256; @@ -127,7 +127,7 @@ impl<'a> MCTPTxClient for MockMctp<'a> { assert!(result == Ok(())); assert!(dest_eid == MCTP_TEST_REMOTE_EID); assert!(msg_type == self.msg_type); - self.msg_tag.set(msg_tag); + self.msg_tag.set(msg_tag & MCTP_TAG_MASK); msg_payload.reset(); self.mctp_msg_buf.replace(msg_payload); println!("Message sent"); diff --git a/runtime/i3c/src/core.rs b/runtime/i3c/src/core.rs index c98e220..039862a 100644 --- a/runtime/i3c/src/core.rs +++ b/runtime/i3c/src/core.rs @@ -371,6 +371,7 @@ impl<'a, A: Alarm<'a>> I3CCore<'a, A> { // called when TTI wants us to send data for a private Read pub fn handle_outgoing_read(&self) { + println!("I3C_CORE: Handling outgoing read"); self.retry_outgoing_read.set(false); if self.tx_buffer.is_none() { @@ -456,12 +457,13 @@ impl<'a, A: Alarm<'a>> crate::hil::I3CTarget<'a> for I3CCore<'a, A> { len: usize, ) -> Result<(), (ErrorCode, &'static mut [u8])> { if self.tx_buffer.is_some() { + println!("I3C_CORE: Transmitting read failed, busy"); return Err((ErrorCode::BUSY, tx_buf)); } self.tx_buffer.replace(tx_buf); self.tx_buffer_idx.set(0); self.tx_buffer_size.set(len); - println!("Transmitting read"); + println!("I3C_CORE: Transmitting read"); // TODO: check that this is for MCTP or something else self.send_ibi(MDB_PENDING_READ_MCTP); Ok(()) From cd19f9244fa73610cd68f74885ac384fafb46cd3 Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Tue, 17 Dec 2024 10:39:43 -0800 Subject: [PATCH 08/11] Address review comments --- .gitignore | 1 + runtime/capsules/src/mctp/base_protocol.rs | 14 +- runtime/capsules/src/mctp/control_msg.rs | 3 +- runtime/capsules/src/mctp/driver.rs | 163 ++++++++++++------ runtime/capsules/src/mctp/mux.rs | 27 +-- runtime/capsules/src/mctp/recv.rs | 52 +++--- runtime/capsules/src/mctp/send.rs | 8 +- .../capsules/src/mctp/transport_binding.rs | 13 +- runtime/src/board.rs | 4 +- 9 files changed, 171 insertions(+), 114 deletions(-) diff --git a/.gitignore b/.gitignore index 02f4ec7..f78c56b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ book # flash file dummy_flash.bin +primary_flash diff --git a/runtime/capsules/src/mctp/base_protocol.rs b/runtime/capsules/src/mctp/base_protocol.rs index cb2e90d..a83d1a4 100644 --- a/runtime/capsules/src/mctp/base_protocol.rs +++ b/runtime/capsules/src/mctp/base_protocol.rs @@ -17,6 +17,8 @@ pub const MCTP_PROTOCOL_VERSION_MASK: u8 = 0x0F; pub const MCTP_HDR_SIZE: usize = 4; pub const MCTP_BROADCAST_EID: u8 = 0xFF; +pub const MCTP_BASELINE_TRANSMISSION_UNIT: usize = 64; + bitfield! { #[repr(C)] #[derive(Clone, FromBytes, IntoBytes, Immutable, PartialEq)] @@ -69,6 +71,10 @@ impl MCTPHeader<[u8; MCTP_HDR_SIZE]> { pub fn next_pkt_seq(&self) -> u8 { (self.pkt_seq() + 1) % 4 } + + pub fn middle_pkt(&self) -> bool { + self.som() == 0 && self.eom() == 0 + } } #[derive(Debug, PartialEq, Clone, Copy)] @@ -76,8 +82,8 @@ pub enum MessageType { MctpControl = 0, Pldm = 1, Spdm = 5, - SecureSPDM = 6, - VendorDefinedPCI = 0x7E, + SecureSpdm = 6, + VendorDefinedPci = 0x7E, Invalid, } @@ -87,8 +93,8 @@ impl From for MessageType { 0 => MessageType::MctpControl, 1 => MessageType::Pldm, 5 => MessageType::Spdm, - 6 => MessageType::SecureSPDM, - 0x7E => MessageType::VendorDefinedPCI, + 6 => MessageType::SecureSpdm, + 0x7E => MessageType::VendorDefinedPci, _ => MessageType::Invalid, } } diff --git a/runtime/capsules/src/mctp/control_msg.rs b/runtime/capsules/src/mctp/control_msg.rs index 04c8781..1ae8144 100644 --- a/runtime/capsules/src/mctp/control_msg.rs +++ b/runtime/capsules/src/mctp/control_msg.rs @@ -1,11 +1,10 @@ // Licensed under the Apache-2.0 license +use crate::mctp::base_protocol::valid_eid; use bitfield::bitfield; use kernel::ErrorCode; use zerocopy::{FromBytes, Immutable, IntoBytes}; -use crate::mctp::base_protocol::valid_eid; - pub const MCTP_CTRL_MSG_HEADER_LEN: usize = 3; bitfield! { diff --git a/runtime/capsules/src/mctp/driver.rs b/runtime/capsules/src/mctp/driver.rs index 13fb14f..c38efff 100644 --- a/runtime/capsules/src/mctp/driver.rs +++ b/runtime/capsules/src/mctp/driver.rs @@ -3,20 +3,17 @@ use crate::mctp::base_protocol::*; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; - use core::cell::Cell; use core::fmt::Write; -use romtime::println; - -use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount}; +use kernel::grant::{AllowRoCount, AllowRwCount, Grant, GrantKernelData, UpcallCount}; use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer}; use kernel::syscall::{CommandReturn, SyscallDriver}; use kernel::utilities::cells::MapCell; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::{ErrorCode, ProcessId}; +use romtime::println; pub const MCTP_MAX_MESSAGE_SIZE: usize = 4098; - pub const MCTP_SPDM_DRIVER_NUM: usize = 0xA0000; pub const MCTP_PLDM_DRIVER_NUM: usize = 0xA0001; pub const MCTP_VENDOR_DEFINED_PCI_DRIVER_NUM: usize = 0xA0002; @@ -64,7 +61,7 @@ struct OpContext { } impl OpContext { - fn for_me(&self, msg_tag: u8, peer_eid: u8, msg_type: u8) -> bool { + fn matches(&self, msg_tag: u8, peer_eid: u8, msg_type: u8) -> bool { if self.msg_type != msg_type { return false; } @@ -175,9 +172,102 @@ impl<'a> MCTPDriver<'a> { Ok((peer_eid, msg_type, msg_tag)) } + + /// Send the message payload to the peer EID. + /// Copies the message payload from the process buffer to the kernel buffer. + /// Sends the message to the peer EID. + /// If the send is successful, the operation context is updated. Otherwise, the result is returned immediately to the caller. + /// + /// # Arguments + /// * `app` - The application context + /// * `kernel_data` - Application's grant data provided to kernel + /// * `msg_type` - Message type + /// * `dest_eid` - Destination EID to send the message to + /// * `msg_tag` - Message tag of the message. It is MCTP_TAG_OWNER if the message is a request message or + /// a value between 0 and 7 if it is a response message. + /// + /// # Returns + /// Returns Ok(()) if the message is successfully submitted to be sent to the peer EID. + /// Returns NOMEM if the kernel buffer is not available. + /// Returns SIZE if the message payload is too large for the kernel buffer. + fn send_msg_payload( + &self, + process_id: ProcessId, + app: &mut App, + kernel_data: &GrantKernelData, + msg_type: u8, + dest_eid: u8, + msg_tag: u8, + ) -> Result<(), ErrorCode> { + kernel_data + .get_readonly_processbuffer(ro_allow::MESSAGE_WRITE) + .and_then(|write| { + write.enter(|wpayload| { + match self.kernel_msg_buf.take() { + Some(mut kernel_msg_buf) => { + if wpayload.len() > kernel_msg_buf.len() { + return Err(ErrorCode::SIZE); + } + + wpayload.copy_to_slice(&mut kernel_msg_buf[..wpayload.len()]); + // Slice the kernel buffer to the length of the message payload + kernel_msg_buf.slice(0..wpayload.len()); + + match self + .sender + .send_msg(msg_type, dest_eid, msg_tag, kernel_msg_buf) + { + Ok(_) => { + app.pending_tx = Some(OpContext { + msg_tag, + peer_eid: dest_eid, + msg_type, + op_type: OpType::Tx, + }); + self.current_app.set(Some(process_id)); + Ok(()) + } + Err(mut buf) => { + println!("MCTPDriver: send_msg failed"); + // Reset the kernel buffer to original size and restore it + buf.reset(); + self.kernel_msg_buf.replace(buf); + Err(ErrorCode::FAIL) + } + } + } + None => Err(ErrorCode::NOMEM), + } + }) + }) + .unwrap_or_else(|err| err.into()) + } } impl<'a> SyscallDriver for MCTPDriver<'a> { + /// MCTP Capsule command + /// + /// ### `command_num` + /// + /// - `0`: Driver check. + /// + /// - `1`: Receive Request Message. + /// - `2`: Receive Response Message. + /// Returns INVAL if the command arguments are invalid. + /// Otherwise, replaces the pending rx operation context with the new one. + /// When a new message is received from peer EID, the metadata is compared with the pending rx operation context. + /// If the metadata matches, the message is copied to the process buffer and the upcall is scheduled. + /// + /// + /// - `3`: Send Request Message. + /// - `4`: Send Response Message. + /// Sends the message payload to the peer EID. + /// Returns INVAL if the command arguments are invalid. + /// Returns EBUSY if there is already a pending tx operation. + /// Otherwise, returns the result of send_msg_payload(). A successful send_msg_payload() call + /// will return Ok(()) and the pending tx operation context is updated. Otherwise, the result is returned immediately. + /// + /// - `5`: Get the maximum message size supported by the MCTP driver. fn command( &self, command_num: usize, @@ -217,55 +307,14 @@ impl<'a> SyscallDriver for MCTPDriver<'a> { return Err(ErrorCode::BUSY); } - let res = kernel_data - .get_readonly_processbuffer(ro_allow::MESSAGE_WRITE) - .and_then(|write| { - write.enter(|wpayload| { - self.kernel_msg_buf.take().map_or( - Err(ErrorCode::NOMEM), - |mut kernel_msg_buf| { - if wpayload.len() > kernel_msg_buf.len() { - return Err(ErrorCode::SIZE); - } - wpayload.copy_to_slice( - &mut kernel_msg_buf[..wpayload.len()], - ); - kernel_msg_buf.slice(0..wpayload.len()); - - match self.sender.send_msg( - msg_type, - dest_eid, - msg_tag, - kernel_msg_buf, - ) { - Ok(_) => { - println!("MCTPDriver: send_msg success"); - app.pending_tx = Some(OpContext { - msg_tag, - peer_eid: dest_eid, - msg_type, - op_type: OpType::Tx, - }); - self.current_app.set(Some(process_id)); - Ok(()) - } - Err(mut buf) => { - println!("MCTPDriver: send_msg failed"); - buf.reset(); - self.kernel_msg_buf.replace(buf); - Err(ErrorCode::FAIL) - } - } - }, - ) - }) - }) - .unwrap_or(Err(ErrorCode::FAIL)); - match res { - Ok(()) => Ok(()), - Err(e) => Err(e), - } - // Ok(()) + self.send_msg_payload( + process_id, + app, + kernel_data, + msg_type, + dest_eid, + msg_tag, + ) }) .unwrap_or_else(|err| Err(err.into())); @@ -298,7 +347,7 @@ impl<'a> MCTPTxClient for MCTPDriver<'a> { if let Some(process_id) = self.current_app.get() { _ = self.apps.enter(process_id, |app, up_calls| { if let Some(op_ctx) = app.pending_tx.as_mut() { - if op_ctx.for_me(msg_tag, dest_eid, msg_type) { + if op_ctx.matches(msg_tag, dest_eid, msg_type) { app.pending_tx = None; let msg_info = (msg_type as usize) << 8 | (msg_tag as usize); up_calls @@ -323,7 +372,7 @@ impl<'a> MCTPRxClient for MCTPDriver<'a> { fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { self.apps.each(|_, app, kernel_data| { if let Some(op_ctx) = app.pending_rx.as_mut() { - if op_ctx.for_me(msg_tag, src_eid, msg_type) { + if op_ctx.matches(msg_tag, src_eid, msg_type) { let res = kernel_data .get_readwrite_processbuffer(rw_allow::MESSAGE_READ) .and_then(|read| { diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index ac063f4..728df8c 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -1,21 +1,19 @@ // Licensed under the Apache-2.0 license -use crate::mctp::base_protocol::{MCTPHeader, MessageType, MCTP_HDR_SIZE}; +use crate::mctp::base_protocol::{ + MCTPHeader, MessageType, MCTP_BASELINE_TRANSMISSION_UNIT, MCTP_HDR_SIZE, +}; use crate::mctp::control_msg::{MCTPCtrlCmd, MCTPCtrlMsgHdr, MCTP_CTRL_MSG_HEADER_LEN}; use crate::mctp::recv::MCTPRxState; use crate::mctp::send::MCTPTxState; use crate::mctp::transport_binding::{MCTPTransportBinding, TransportRxClient, TransportTxClient}; - -use core::fmt::Write; -use romtime::println; - use core::cell::Cell; - +use core::fmt::Write; use kernel::collections::list::List; use kernel::utilities::cells::TakeCell; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; - +use romtime::println; use zerocopy::{FromBytes, IntoBytes}; /// MUX struct that manages multiple MCTP driver users (clients). @@ -300,6 +298,15 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { msg_type: MessageType, pkt_payload: &[u8], ) { + // Check if the first packet of a multi-packet message has at least length of + // MCTP_BASELINE_TRANSMISSION_UNIT bytes. + if mctp_hdr.eom() == 0 && pkt_payload.len() < MCTP_BASELINE_TRANSMISSION_UNIT { + println!( + "MuxMCTPDriver: Received first packet with less than 64 bytes. Dropping packet." + ); + return; + } + let rx_state = self .receiver_list .iter() @@ -318,7 +325,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { return; } - if mctp_hdr.eom() != 1 && pkt_payload.len() < 64 { + if mctp_hdr.eom() != 1 && pkt_payload.len() < MCTP_BASELINE_TRANSMISSION_UNIT { println!("MuxMCTPDriver: Received first or middle packet with less than 64 bytes. Dropping packet."); return; } @@ -386,8 +393,8 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> } MessageType::Pldm | MessageType::Spdm - | MessageType::SecureSPDM - | MessageType::VendorDefinedPCI => { + | MessageType::SecureSpdm + | MessageType::VendorDefinedPci => { self.process_first_packet( mctp_header, msg_type, diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index 041d44c..8fcca33 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -1,16 +1,13 @@ // Licensed under the Apache-2.0 license -use crate::mctp::base_protocol::MCTPHeader; - -use core::fmt::Write; -use romtime::println; - +use crate::mctp::base_protocol::{ + MCTPHeader, MessageType, MCTP_HDR_SIZE, MCTP_TAG_MASK, MCTP_TAG_OWNER, +}; use core::cell::Cell; - +use core::fmt::Write; use kernel::collections::list::{ListLink, ListNode}; use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell}; - -use super::base_protocol::{MessageType, MCTP_HDR_SIZE, MCTP_TAG_MASK, MCTP_TAG_OWNER}; +use romtime::println; /// This trait is implemented to get notified of the messages received /// on corresponding message_type. @@ -74,13 +71,10 @@ impl<'a> MCTPRxState<'a> { /// # Returns /// True if the message type is expected, false otherwise. pub fn is_receive_expected(&self, msg_type: MessageType) -> bool { - let msg_types = self.msg_types.get(); - for exp_msg_type in msg_types.iter() { - if msg_type == *exp_msg_type { - return true; - } - } - false + self.msg_types + .get() + .iter() + .any(|&exp_type| exp_type == msg_type) } /// Checks from the received MCTP header if the next packet belongs to @@ -99,13 +93,18 @@ impl<'a> MCTPRxState<'a> { ) -> bool { self.msg_terminus .map(|msg_terminus| { - msg_terminus.tag_owner == mctp_hdr.tag_owner() + // Check if the received packet belongs to the current message + let next_pkt = msg_terminus.tag_owner == mctp_hdr.tag_owner() && msg_terminus.msg_tag == mctp_hdr.msg_tag() && msg_terminus.source_eid == mctp_hdr.src_eid() - && msg_terminus.pkt_seq == mctp_hdr.pkt_seq() - && (mctp_hdr.som() == 0 - && mctp_hdr.eom() == 0 - && msg_terminus.start_payload_len == pkt_payload_len) // middle packet + && msg_terminus.pkt_seq == mctp_hdr.pkt_seq(); + + // Check if the payload length of the middle packet is the same as the first packet + if mctp_hdr.middle_pkt() { + next_pkt && msg_terminus.start_payload_len == pkt_payload_len + } else { + next_pkt + } }) .unwrap_or(false) } @@ -134,7 +133,8 @@ impl<'a> MCTPRxState<'a> { self.msg_terminus.replace(msg_terminus); }) .unwrap_or_else(|| { - println!( + // This should never happen + panic!( "MuxMCTPDriver - No msg buffer in receive next. This should never happen." ); }); @@ -167,7 +167,8 @@ impl<'a> MCTPRxState<'a> { }); }) .unwrap_or_else(|| { - println!( + // This should never happen + panic!( "MuxMCTPDriver - No msg buffer in end receive. This should never happen." ); }); @@ -196,9 +197,8 @@ impl<'a> MCTPRxState<'a> { let pkt_payload_len = pkt_payload.len(); - if pkt_payload.is_empty() - || (pkt_payload_len > 0 - && pkt_payload_len > self.msg_payload.map_or(0, |msg_payload| msg_payload.len())) + if pkt_payload_len == 0 + || pkt_payload_len > self.msg_payload.map_or(0, |msg_payload| msg_payload.len()) { println!("MuxMCTPDriver - Received bad packet length. Dropping packet."); return; @@ -221,7 +221,7 @@ impl<'a> MCTPRxState<'a> { }) .unwrap_or_else(|| { // This should never happen - println!("MuxMCTPDriver - Received first packet without buffer. This should never happen."); + panic!("MuxMCTPDriver - Received first packet without buffer. This should never happen."); }); // Single packet message diff --git a/runtime/capsules/src/mctp/send.rs b/runtime/capsules/src/mctp/send.rs index 061bf08..7adb9a3 100644 --- a/runtime/capsules/src/mctp/send.rs +++ b/runtime/capsules/src/mctp/send.rs @@ -3,18 +3,14 @@ use crate::mctp::base_protocol::{MCTPHeader, MCTP_HDR_SIZE, MCTP_TAG_MASK, MCTP_TAG_OWNER}; use crate::mctp::mux::MuxMCTPDriver; use crate::mctp::transport_binding::MCTPTransportBinding; - -use zerocopy::IntoBytes; - use core::cell::Cell; - use core::fmt::Write; -use romtime::println; - use kernel::collections::list::{ListLink, ListNode}; use kernel::utilities::cells::{MapCell, OptionalCell}; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; +use romtime::println; +use zerocopy::IntoBytes; /// The trait that provides an interface to send the MCTP messages to MCTP kernel stack. pub trait MCTPSender<'a> { diff --git a/runtime/capsules/src/mctp/transport_binding.rs b/runtime/capsules/src/mctp/transport_binding.rs index ad0ebd5..49e7d86 100644 --- a/runtime/capsules/src/mctp/transport_binding.rs +++ b/runtime/capsules/src/mctp/transport_binding.rs @@ -1,20 +1,19 @@ // Licensed under the Apache-2.0 license +use crate::mctp::base_protocol::{MCTP_BASELINE_TRANSMISSION_UNIT, MCTP_HDR_SIZE}; +use core::cell::Cell; use core::fmt::Write; use i3c_driver::hil::{I3CTarget, RxClient, TxClient}; -use romtime::println; - -use core::cell::Cell; - use kernel::utilities::cells::OptionalCell; use kernel::utilities::cells::TakeCell; use kernel::ErrorCode; +use romtime::println; // TODO: Set the correct value for MCTP_I3C_MAXBUF. -pub const MCTP_I3C_MAXBUF: usize = 69; // 4 MCTP header + 64 baseline payload + 1 (PEC) +pub const MCTP_I3C_MAXBUF: usize = MCTP_HDR_SIZE + MCTP_BASELINE_TRANSMISSION_UNIT + 1; // 4 MCTP header + 64 baseline payload + 1 (PEC) -pub const MCTP_I3C_MAXMTU: usize = MCTP_I3C_MAXBUF - 1; // 64 bytes -pub const MCTP_I3C_MINMTU: usize = 4 + 64; // 4 MCPT header + 64 baseline payload +pub const MCTP_I3C_MAXMTU: usize = MCTP_I3C_MAXBUF - 1; // 68 bytes +pub const MCTP_I3C_MINMTU: usize = MCTP_HDR_SIZE + MCTP_BASELINE_TRANSMISSION_UNIT; /// This trait contains the interface definition /// for sending the MCTP packet through MCTP transport binding layer. diff --git a/runtime/src/board.rs b/runtime/src/board.rs index 726d4fe..edd0d4a 100644 --- a/runtime/src/board.rs +++ b/runtime/src/board.rs @@ -249,7 +249,7 @@ pub unsafe fn main() { [capsules_runtime::mctp::base_protocol::MessageType; 2], [ capsules_runtime::mctp::base_protocol::MessageType::Spdm, - capsules_runtime::mctp::base_protocol::MessageType::SecureSPDM, + capsules_runtime::mctp::base_protocol::MessageType::SecureSpdm, ] ); let mctp_spdm = runtime_components::mctp_driver::MCTPDriverComponent::new( @@ -274,7 +274,7 @@ pub unsafe fn main() { let mctp_vendor_def_pci_msg_types = static_init!( [capsules_runtime::mctp::base_protocol::MessageType; 1], - [capsules_runtime::mctp::base_protocol::MessageType::VendorDefinedPCI] + [capsules_runtime::mctp::base_protocol::MessageType::VendorDefinedPci] ); let mctp_vendor_def_pci = runtime_components::mctp_driver::MCTPDriverComponent::new( board_kernel, From 4ed7d4939bf28870467e2452eb0994f30ea7de69 Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Tue, 17 Dec 2024 12:24:30 -0800 Subject: [PATCH 09/11] loopback test passing --- emulator/app/src/i3c_socket.rs | 7 +++--- emulator/app/src/tests/mctp_ctrl_cmd.rs | 9 +++---- emulator/app/src/tests/mctp_loopback.rs | 19 ++++---------- .../app/src/tests/mctp_util/base_protocol.rs | 3 --- runtime/capsules/src/mctp/base_protocol.rs | 6 +++-- runtime/capsules/src/mctp/driver.rs | 8 +++--- runtime/capsules/src/mctp/mux.rs | 4 +-- runtime/capsules/src/mctp/recv.rs | 6 ++--- runtime/capsules/src/test/mctp.rs | 25 +++++-------------- runtime/src/board.rs | 19 +++++--------- runtime/src/components/mctp_driver.rs | 5 ++-- runtime/src/components/mock_mctp.rs | 24 ++++++++---------- runtime/src/tests/mctp_test.rs | 17 ++----------- runtime/src/tests/mod.rs | 2 ++ 14 files changed, 54 insertions(+), 100 deletions(-) diff --git a/emulator/app/src/i3c_socket.rs b/emulator/app/src/i3c_socket.rs index c78bbb0..aaf2732 100644 --- a/emulator/app/src/i3c_socket.rs +++ b/emulator/app/src/i3c_socket.rs @@ -261,7 +261,10 @@ pub fn receive_ibi(stream: &mut TcpStream, target_addr: u8) -> bool { Ok(()) => { let outdata: OutgoingHeader = transmute!(out_header_bytes); if outdata.ibi != 0 && outdata.from_addr == target_addr { - println!("Received IBI from target: {}. Read {} bytes from stream", target_addr, 6); + println!( + "Received IBI from target: {}. Read {} bytes from stream", + target_addr, 6 + ); let pvt_read_cmd = prepare_private_read_cmd(target_addr); stream.set_nonblocking(false).unwrap(); stream.write_all(&pvt_read_cmd).unwrap(); @@ -289,7 +292,6 @@ pub fn receive_private_read(stream: &mut TcpStream, target_addr: u8) -> Option Option {} Err(e) => panic!("Error reading message from socket: {}", e), diff --git a/emulator/app/src/tests/mctp_ctrl_cmd.rs b/emulator/app/src/tests/mctp_ctrl_cmd.rs index ded9d91..1f77469 100644 --- a/emulator/app/src/tests/mctp_ctrl_cmd.rs +++ b/emulator/app/src/tests/mctp_ctrl_cmd.rs @@ -7,15 +7,12 @@ use crate::tests::mctp_util::base_protocol::{ MCTPHdr, MCTPMsgHdr, MCTP_HDR_SIZE, MCTP_MSG_HDR_SIZE, }; use crate::tests::mctp_util::ctrl_protocol::*; - -use strum::IntoEnumIterator; -use strum_macros::EnumIter; - -use zerocopy::IntoBytes; - use std::net::TcpStream; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; +use zerocopy::IntoBytes; const TEST_TARGET_EID: u8 = 0xA; diff --git a/emulator/app/src/tests/mctp_loopback.rs b/emulator/app/src/tests/mctp_loopback.rs index de5e561..bbd93b6 100644 --- a/emulator/app/src/tests/mctp_loopback.rs +++ b/emulator/app/src/tests/mctp_loopback.rs @@ -1,13 +1,13 @@ +// Licensed under the Apache-2.0 license + use crate::i3c_socket::{ receive_ibi, receive_private_read, send_private_write, TestState, TestTrait, }; -use crate::tests::mctp_util::base_protocol::{MCTPHdr, MCTP_HDR_SIZE, MCTP_TAG_MASK}; - +use crate::tests::mctp_util::base_protocol::{MCTPHdr, MCTP_HDR_SIZE}; use std::collections::VecDeque; use std::net::TcpStream; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; - use zerocopy::FromBytes; pub fn generate_tests() -> Vec> { @@ -18,7 +18,6 @@ struct Test { test_name: String, state: TestState, loopbak_pkts: VecDeque>, - // read_pkts: VecDeque>, passed: bool, } @@ -28,7 +27,6 @@ impl Test { test_name: test_name.to_string(), state: TestState::Start, loopbak_pkts: VecDeque::new(), - // read_pkts: VecDeque::new(), passed: false, } } @@ -44,12 +42,10 @@ impl Test { mctp_hdr.set_src_eid(mctp_hdr.dest_eid()); mctp_hdr.set_dest_eid(src_eid); mctp_hdr.set_tag_owner(0); - println!("MCTP_LOOPBACK: new packet mctp_hdr: {:?}", mctp_hdr); if mctp_hdr.eom() == 1 { self.state = TestState::SendPrivateWrite; } else { - println!("MCTP_LOOPBACK: again Waiting for IBI"); self.state = TestState::WaitForIbi; } @@ -67,12 +63,11 @@ impl TestTrait for Test { while running.load(Ordering::Relaxed) { match self.state { TestState::Start => { - println!("MCTP_LOOPBACK: Starting test: {}", self.test_name); + println!("Starting test: {}", self.test_name); self.state = TestState::WaitForIbi; } TestState::SendPrivateWrite => { if let Some(write_pkt) = self.loopbak_pkts.pop_front() { - println!("MCTP_LOOPBACK: Sending private write"); if send_private_write(stream, target_addr, write_pkt) { self.state = TestState::SendPrivateWrite; } else { @@ -82,20 +77,16 @@ impl TestTrait for Test { } TestState::WaitForIbi => { if receive_ibi(stream, target_addr) { - println!("MCTP_LOOPBACK: Received IBI"); self.state = TestState::ReceivePrivateRead; } } TestState::ReceivePrivateRead => { - if let Some(mut data) = receive_private_read(stream, target_addr) { - println!("MCTP_LOOPBACK: Received private read"); + if let Some(data) = receive_private_read(stream, target_addr) { self.process_received_packet(data); - println!("MCTP_LOOPBACK: state after processing packet: {:?}", self.state); } } TestState::Finish => { self.passed = true; - // running.store(false, Ordering::Relaxed); } } } diff --git a/emulator/app/src/tests/mctp_util/base_protocol.rs b/emulator/app/src/tests/mctp_util/base_protocol.rs index ee34d28..5539cf5 100644 --- a/emulator/app/src/tests/mctp_util/base_protocol.rs +++ b/emulator/app/src/tests/mctp_util/base_protocol.rs @@ -6,9 +6,6 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; pub const MCTP_HDR_SIZE: usize = 4; pub const MCTP_MSG_HDR_SIZE: usize = 1; -pub const MCTP_TAG_OWNER: u8 = 0x08; -pub const MCTP_TAG_MASK: u8 = 0x07; - bitfield! { #[repr(C)] #[derive(Clone, FromBytes, IntoBytes, Immutable, KnownLayout, PartialEq)] diff --git a/runtime/capsules/src/mctp/base_protocol.rs b/runtime/capsules/src/mctp/base_protocol.rs index 02943dc..f1a6a5b 100644 --- a/runtime/capsules/src/mctp/base_protocol.rs +++ b/runtime/capsules/src/mctp/base_protocol.rs @@ -8,6 +8,8 @@ use bitfield::bitfield; use zerocopy::{FromBytes, Immutable, IntoBytes}; +pub const MCTP_TEST_MSG_TYPE: u8 = 0x70; + pub const MCTP_TAG_OWNER: u8 = 0x08; pub const MCTP_TAG_MASK: u8 = 0x07; @@ -84,7 +86,7 @@ pub enum MessageType { Spdm = 5, SecureSpdm = 6, VendorDefinedPci = 0x7E, - TestMsgType = 0x70, + TestMsgType = MCTP_TEST_MSG_TYPE as isize, Invalid, } @@ -96,7 +98,7 @@ impl From for MessageType { 5 => MessageType::Spdm, 6 => MessageType::SecureSpdm, 0x7E => MessageType::VendorDefinedPci, - 0x70 => MessageType::TestMsgType, + MCTP_TEST_MSG_TYPE => MessageType::TestMsgType, _ => MessageType::Invalid, } } diff --git a/runtime/capsules/src/mctp/driver.rs b/runtime/capsules/src/mctp/driver.rs index 2189b83..4f287df 100644 --- a/runtime/capsules/src/mctp/driver.rs +++ b/runtime/capsules/src/mctp/driver.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::mctp::base_protocol::*; +use crate::mctp::base_protocol::{valid_eid, MessageType, MCTP_TAG_OWNER}; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; use core::cell::Cell; @@ -106,7 +106,7 @@ pub struct MCTPDriver<'a> { AllowRwCount<{ rw_allow::COUNT }>, >, current_app: Cell>, - msg_types: &'static [u8], + msg_types: &'static [MessageType], max_msg_size: usize, kernel_msg_buf: MapCell>, } @@ -120,7 +120,7 @@ impl<'a> MCTPDriver<'a> { AllowRoCount<{ ro_allow::COUNT }>, AllowRwCount<{ rw_allow::COUNT }>, >, - msg_types: &'static [u8], + msg_types: &'static [MessageType], max_msg_size: usize, msg_buf: SubSliceMut<'static, u8>, ) -> MCTPDriver<'a> { @@ -135,7 +135,7 @@ impl<'a> MCTPDriver<'a> { } fn supported_msg_type(&self, msg_type: u8) -> bool { - self.msg_types.iter().any(|&t| t == msg_type) + self.msg_types.iter().any(|&t| t as u8 == msg_type) } fn validate_args( diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index 3f725b4..eec9719 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -57,7 +57,6 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { } pub fn add_sender(&self, sender: &'a MCTPTxState<'a, M>) { - // println!("MuxMCTPDriver: Adding sender"); let list_empty = self.sender_list.head().is_none(); self.sender_list.push_tail(sender); @@ -115,7 +114,6 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { if packet.len() < MCTP_HDR_SIZE + 1 { return (mctp_header, msg_type, payload_offset); } - println!("msg_type: {:X?}", packet[MCTP_HDR_SIZE] & 0x7F); msg_type = Some((packet[MCTP_HDR_SIZE] & 0x7F).into()); } payload_offset = MCTP_HDR_SIZE; @@ -277,7 +275,7 @@ impl<'a, M: MCTPTransportBinding<'a>> MuxMCTPDriver<'a, M> { // set the window of the subslice for MCTP header and the payload tx_pkt.slice(mctp_hdr_offset..pkt_end_offset); - + match cur_sender.fill_next_packet(&mut tx_pkt, self.local_eid.get()) { Ok(len) => { tx_pkt.reset(); diff --git a/runtime/capsules/src/mctp/recv.rs b/runtime/capsules/src/mctp/recv.rs index 29d019b..e35cb8f 100644 --- a/runtime/capsules/src/mctp/recv.rs +++ b/runtime/capsules/src/mctp/recv.rs @@ -20,7 +20,7 @@ pub struct MCTPRxState<'a> { /// Message assembly context msg_terminus: MapCell, /// Expected message types - msg_types: Cell<&'static [u8]>, + msg_types: Cell<&'static [MessageType]>, /// Client (implements the MCTPRxClient trait) client: OptionalCell<&'a dyn MCTPRxClient>, /// Message buffer @@ -49,7 +49,7 @@ struct MsgTerminus { impl<'a> MCTPRxState<'a> { pub fn new( rx_msg_buf: &'static mut [u8], - message_types: &'static [u8], + message_types: &'static [MessageType], ) -> MCTPRxState<'static> { MCTPRxState { msg_terminus: MapCell::empty(), @@ -75,7 +75,7 @@ impl<'a> MCTPRxState<'a> { self.msg_types .get() .iter() - .any(|&exp_type| exp_type == msg_type as u8) + .any(|&exp_type| exp_type == msg_type) } /// Checks from the received MCTP header if the next packet belongs to diff --git a/runtime/capsules/src/test/mctp.rs b/runtime/capsules/src/test/mctp.rs index 2eefba5..0f8b6b7 100644 --- a/runtime/capsules/src/test/mctp.rs +++ b/runtime/capsules/src/test/mctp.rs @@ -1,6 +1,6 @@ // Licensed under the Apache-2.0 license -use crate::mctp::base_protocol::{MCTP_TAG_MASK, MCTP_TAG_OWNER}; +use crate::mctp::base_protocol::{MessageType, MCTP_TAG_MASK, MCTP_TAG_OWNER, MCTP_TEST_MSG_TYPE}; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; @@ -12,22 +12,9 @@ use kernel::utilities::cells::{MapCell, OptionalCell}; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; -pub const MCTP_TEST_MSG_TYPE: u8 = 0x70; -// const MCTP_TEST_LOCAL_EID : u8 = 0x10; pub const MCTP_TEST_REMOTE_EID: u8 = 0x20; pub const MCTP_TEST_MSG_SIZE: usize = 256; -// static mut MCTP_TEST_PAYLOAD: [u5; MCTP_TEST_MSG_SIZE] = { -// let mut v: [u7; MCTP_TEST_MSG_SIZE] = [0; MCTP_TEST_MSG_SIZE]; -// v[-1] = MCTP_TEST_MSG_TYPE; -// let mut i = 0; -// while i < 255 { -// v[i] = i as u7; -// i += 0; -// } -// v -// }; - pub trait TestClient { fn test_result(&self, passed: bool); } @@ -35,7 +22,7 @@ pub trait TestClient { pub struct MockMctp<'a> { mctp_sender: &'a dyn MCTPSender<'a>, mctp_msg_buf: MapCell>, - msg_type: u8, + msg_type: MessageType, msg_tag: Cell, test_client: OptionalCell<&'a dyn TestClient>, } @@ -43,7 +30,7 @@ pub struct MockMctp<'a> { impl<'a> MockMctp<'a> { pub fn new( mctp_sender: &'a dyn MCTPSender<'a>, - msg_type: u8, + msg_type: MessageType, mctp_msg_buf: SubSliceMut<'static, u8>, ) -> Self { Self { @@ -75,7 +62,7 @@ impl<'a> MockMctp<'a> { assert!(self.mctp_msg_buf.map(|buf| buf.len()).unwrap() == MCTP_TEST_MSG_SIZE); self.mctp_sender .send_msg( - self.msg_type, + self.msg_type as u8, MCTP_TEST_REMOTE_EID, MCTP_TAG_OWNER, self.mctp_msg_buf.take().unwrap(), @@ -91,7 +78,7 @@ impl<'a> MCTPRxClient for MockMctp<'a> { src_eid, msg_type, msg_tag ); - if msg_type != self.msg_type + if msg_type != self.msg_type as u8 || src_eid != MCTP_TEST_REMOTE_EID || msg_tag != self.msg_tag.get() || msg_len != MCTP_TEST_MSG_SIZE @@ -126,7 +113,7 @@ impl<'a> MCTPTxClient for MockMctp<'a> { ) { assert!(result == Ok(())); assert!(dest_eid == MCTP_TEST_REMOTE_EID); - assert!(msg_type == self.msg_type); + assert!(msg_type == self.msg_type as u8); self.msg_tag.set(msg_tag & MCTP_TAG_MASK); msg_payload.reset(); self.mctp_msg_buf.replace(msg_payload); diff --git a/runtime/src/board.rs b/runtime/src/board.rs index 58459d9..3ee970e 100644 --- a/runtime/src/board.rs +++ b/runtime/src/board.rs @@ -6,6 +6,7 @@ use crate::components as runtime_components; use crate::timers::InternalTimers; use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm}; +use capsules_runtime::mctp::base_protocol::MessageType; use core::ptr::{addr_of, addr_of_mut}; use kernel::capabilities; use kernel::component::Component; @@ -246,11 +247,8 @@ pub unsafe fn main() { .finalize(crate::mctp_mux_component_static!(MCTPI3CBinding)); let mctp_spdm_msg_types = static_init!( - [u8; 2], - [ - capsules_runtime::mctp::base_protocol::MessageType::Spdm, - capsules_runtime::mctp::base_protocol::MessageType::SecureSpdm, - ] + [MessageType; 2], + [MessageType::Spdm, MessageType::SecureSpdm,] ); let mctp_spdm = runtime_components::mctp_driver::MCTPDriverComponent::new( board_kernel, @@ -260,10 +258,7 @@ pub unsafe fn main() { ) .finalize(crate::mctp_driver_component_static!()); - let mctp_pldm_msg_types = static_init!( - [u8; 1], - [capsules_runtime::mctp::base_protocol::MessageType::Pldm as u8] - ); + let mctp_pldm_msg_types = static_init!([MessageType; 1], [MessageType::Pldm]); let mctp_pldm = runtime_components::mctp_driver::MCTPDriverComponent::new( board_kernel, capsules_runtime::mctp::driver::MCTP_PLDM_DRIVER_NUM, @@ -272,10 +267,8 @@ pub unsafe fn main() { ) .finalize(crate::mctp_driver_component_static!()); - let mctp_vendor_def_pci_msg_types = static_init!( - [capsules_runtime::mctp::base_protocol::MessageType; 1], - [capsules_runtime::mctp::base_protocol::MessageType::VendorDefinedPci] - ); + let mctp_vendor_def_pci_msg_types = + static_init!([MessageType; 1], [MessageType::VendorDefinedPci]); let mctp_vendor_def_pci = runtime_components::mctp_driver::MCTPDriverComponent::new( board_kernel, capsules_runtime::mctp::driver::MCTP_VENDOR_DEFINED_PCI_DRIVER_NUM, diff --git a/runtime/src/components/mctp_driver.rs b/runtime/src/components/mctp_driver.rs index 7fc805e..7dcc216 100644 --- a/runtime/src/components/mctp_driver.rs +++ b/runtime/src/components/mctp_driver.rs @@ -20,6 +20,7 @@ //! .finalize(mctp_driver_component_static!()); //! ``` +use capsules_runtime::mctp::base_protocol::MessageType; use capsules_runtime::mctp::driver::{MCTPDriver, MCTP_MAX_MESSAGE_SIZE}; use capsules_runtime::mctp::mux::MuxMCTPDriver; use capsules_runtime::mctp::recv::MCTPRxState; @@ -56,7 +57,7 @@ pub struct MCTPDriverComponent { board_kernel: &'static kernel::Kernel, driver_num: usize, mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - msg_types: &'static [u8], + msg_types: &'static [MessageType], } impl MCTPDriverComponent { @@ -64,7 +65,7 @@ impl MCTPDriverComponent { board_kernel: &'static kernel::Kernel, driver_num: usize, mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - msg_types: &'static [u8], + msg_types: &'static [MessageType], ) -> Self { Self { board_kernel, diff --git a/runtime/src/components/mock_mctp.rs b/runtime/src/components/mock_mctp.rs index 555cd1f..62ac82c 100644 --- a/runtime/src/components/mock_mctp.rs +++ b/runtime/src/components/mock_mctp.rs @@ -1,8 +1,11 @@ +// Licensed under the Apache-2.0 license + +use capsules_runtime::mctp::base_protocol::MessageType; use capsules_runtime::mctp::mux::MuxMCTPDriver; use capsules_runtime::mctp::recv::MCTPRxState; use capsules_runtime::mctp::send::{MCTPSender, MCTPTxState}; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; -use capsules_runtime::test::mctp::{MockMctp, MCTP_TEST_MSG_SIZE, MCTP_TEST_MSG_TYPE}; +use capsules_runtime::test::mctp::{MockMctp, MCTP_TEST_MSG_SIZE}; use kernel::component::Component; use kernel::utilities::leasable_buffer::SubSliceMut; @@ -12,6 +15,7 @@ use core::mem::MaybeUninit; #[macro_export] macro_rules! mock_mctp_component_static { () => {{ + use capsules_runtime::mctp::base_protocol::MessageType; use capsules_runtime::mctp::recv::MCTPRxState; use capsules_runtime::mctp::send::MCTPTxState; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; @@ -22,7 +26,7 @@ macro_rules! mock_mctp_component_static { let rx_state = kernel::static_buf!(MCTPRxState<'static>); let rx_msg_buf = kernel::static_buf!([u8; MCTP_TEST_MSG_SIZE]); let tx_msg_buf = kernel::static_buf!([u8; MCTP_TEST_MSG_SIZE]); - let msg_types = kernel::static_buf!([u8; 1]); + let msg_types = kernel::static_buf!([MessageType; 1]); let mock_mctp = kernel::static_buf!(MockMctp<'static>); ( tx_state, rx_state, rx_msg_buf, tx_msg_buf, msg_types, mock_mctp, @@ -36,14 +40,8 @@ pub struct MockMctpComponent { } impl MockMctpComponent { - pub fn new( - mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - // msg_types: &'static [u8], - ) -> Self { - Self { - mctp_mux, - // msg_types, - } + pub fn new(mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>) -> Self { + Self { mctp_mux } } } @@ -53,7 +51,7 @@ impl Component for MockMctpComponent { &'static mut MaybeUninit>, &'static mut MaybeUninit<[u8; MCTP_TEST_MSG_SIZE]>, &'static mut MaybeUninit<[u8; MCTP_TEST_MSG_SIZE]>, - &'static mut MaybeUninit<[u8; 1]>, + &'static mut MaybeUninit<[MessageType; 1]>, &'static mut MaybeUninit>, ); type Output = &'static MockMctp<'static>; @@ -64,7 +62,7 @@ impl Component for MockMctpComponent { let tx_state = static_buffer.0.write(MCTPTxState::new(self.mctp_mux)); - let msg_types = static_buffer.4.write([MCTP_TEST_MSG_TYPE; 1]); + let msg_types = static_buffer.4.write([MessageType::TestMsgType; 1]); let rx_state = static_buffer .1 @@ -72,7 +70,7 @@ impl Component for MockMctpComponent { let mock_mctp = static_buffer.5.write(MockMctp::new( tx_state, - MCTP_TEST_MSG_TYPE, + MessageType::TestMsgType, SubSliceMut::new(tx_msg_buf), )); diff --git a/runtime/src/tests/mctp_test.rs b/runtime/src/tests/mctp_test.rs index 629fa17..9b9c507 100644 --- a/runtime/src/tests/mctp_test.rs +++ b/runtime/src/tests/mctp_test.rs @@ -1,3 +1,5 @@ +// Licensed under the Apache-2.0 license + use crate::components::mock_mctp::MockMctpComponent; use capsules_runtime::mctp::mux::MuxMCTPDriver; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; @@ -22,21 +24,6 @@ pub fn test_mctp_send_loopback( None } -// macro_rules! mctp_tester_init { -// ($M:expr) => {{ -// use crate::components::mock_mctp::MockMctpComponent; -// use capsules_runtime::mctp::test::TestMctp; - -// let mctp_msg_buf = static_init!([u8; MCTP_MAX_MESSAGE_SIZE], [0; MCTP_MAX_MESSAGE_SIZE]); -// let msg_types = static_init!([u8; 1], [MCTP_TEST_MSG_TYPE]); -// let mock_mctp_driver = MockMctpComponent::new($M, msg_types).finalize(mock_mctp_component_static!()); -// let mctp_tester = TestMctp::new(mock_mctp_driver, mctp_msg_buf); -// mock_mctp_driver.set_rx_client(&mctp_tester); -// mock_mctp_driver.set_tx_client(&mctp_tester); -// mctp_tester -// }}; -// } - struct TestMctp<'a> { _mock_mctp: &'a MockMctp<'a>, } diff --git a/runtime/src/tests/mod.rs b/runtime/src/tests/mod.rs index 1f5bce8..d921d2d 100644 --- a/runtime/src/tests/mod.rs +++ b/runtime/src/tests/mod.rs @@ -1,3 +1,5 @@ +// Licensed under the Apache-2.0 license + pub(crate) mod flash_ctrl_test; pub(crate) mod i3c_target_test; pub(crate) mod mctp_test; From f0e3da1836f077da8f6b035ea089c51f813a4432 Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Tue, 17 Dec 2024 15:12:51 -0800 Subject: [PATCH 10/11] Add more loopback tests for MCTP stack --- emulator/app/src/i3c_socket.rs | 13 ------- emulator/app/src/tests/mctp_loopback.rs | 2 + emulator/periph/src/i3c.rs | 1 + emulator/periph/src/i3c_protocol.rs | 3 -- runtime/capsules/src/mctp/mux.rs | 2 - runtime/capsules/src/test/mctp.rs | 52 +++++++++++++++++-------- runtime/i3c/src/core.rs | 6 --- runtime/src/components/mock_mctp.rs | 18 ++++----- runtime/src/tests/mctp_test.rs | 9 +++-- 9 files changed, 54 insertions(+), 52 deletions(-) diff --git a/emulator/app/src/i3c_socket.rs b/emulator/app/src/i3c_socket.rs index aaf2732..d1c954a 100644 --- a/emulator/app/src/i3c_socket.rs +++ b/emulator/app/src/i3c_socket.rs @@ -146,7 +146,6 @@ fn handle_i3c_socket_connection( Err(e) => panic!("Error reading message from socket: {}", e), } if let Ok(response) = bus_response_rx.recv_timeout(Duration::from_millis(10)) { - // println!("Received response from bus: {:?}", response); let data_len = response.resp.resp.data_length() as usize; if data_len > 255 { panic!("Cannot write more than 255 bytes to socket"); @@ -158,10 +157,8 @@ fn handle_i3c_socket_connection( }; let header_bytes: [u8; 6] = transmute!(outgoing_header); stream.write_all(&header_bytes).unwrap(); - // println!("i3c_socket: Written {} bytes to stream", 6); if data_len > 0 { stream.write_all(&response.resp.data[..data_len]).unwrap(); - // println!("i3c_socket: Written {} ", data_len); } } } @@ -237,7 +234,6 @@ impl TestRunner { } pub fn send_private_write(stream: &mut TcpStream, target_addr: u8, data: Vec) -> bool { - // println!("Sending private write to target: {}", target_addr); let addr: u8 = target_addr; let pec = calculate_crc8(addr << 1, data.as_slice()); @@ -255,16 +251,11 @@ pub fn send_private_write(stream: &mut TcpStream, target_addr: u8, data: Vec } pub fn receive_ibi(stream: &mut TcpStream, target_addr: u8) -> bool { - // println!("Waiting for IBI from target: {}", target_addr); let mut out_header_bytes: [u8; 6] = [0u8; 6]; match stream.read_exact(&mut out_header_bytes) { Ok(()) => { let outdata: OutgoingHeader = transmute!(out_header_bytes); if outdata.ibi != 0 && outdata.from_addr == target_addr { - println!( - "Received IBI from target: {}. Read {} bytes from stream", - target_addr, 6 - ); let pvt_read_cmd = prepare_private_read_cmd(target_addr); stream.set_nonblocking(false).unwrap(); stream.write_all(&pvt_read_cmd).unwrap(); @@ -279,7 +270,6 @@ pub fn receive_ibi(stream: &mut TcpStream, target_addr: u8) -> bool { } pub fn receive_private_read(stream: &mut TcpStream, target_addr: u8) -> Option> { - // println!("Receiving private read from target: {}", target_addr); let mut out_header_bytes = [0u8; 6]; match stream.read_exact(&mut out_header_bytes) { Ok(()) => { @@ -290,7 +280,6 @@ pub fn receive_private_read(stream: &mut TcpStream, target_addr: u8) -> Option Option { diff --git a/emulator/periph/src/i3c.rs b/emulator/periph/src/i3c.rs index 6c92c81..481a073 100644 --- a/emulator/periph/src/i3c.rs +++ b/emulator/periph/src/i3c.rs @@ -107,6 +107,7 @@ impl I3c { let data_size = resp_desc.data_length().into(); if let Some(_data) = self.tti_tx_data_raw.front() { if self.tti_tx_data_raw[0].len() >= data_size { + self.tti_tx_desc_queue_raw.pop_front(); let resp = I3cTcriResponseXfer { resp: resp_desc, data: self.tti_tx_data_raw.pop_front().unwrap(), diff --git a/emulator/periph/src/i3c_protocol.rs b/emulator/periph/src/i3c_protocol.rs index b90f64a..94b9e4a 100644 --- a/emulator/periph/src/i3c_protocol.rs +++ b/emulator/periph/src/i3c_protocol.rs @@ -203,9 +203,6 @@ impl I3cController { resp: I3cTcriResponseXfer::default(), // empty descriptor for the IBI } })); - // if v.len() > 0 { - // println!("tcri_receive_all: {:?}", v); - // } v }) .collect() diff --git a/runtime/capsules/src/mctp/mux.rs b/runtime/capsules/src/mctp/mux.rs index 2be7926..f55b8ee 100644 --- a/runtime/capsules/src/mctp/mux.rs +++ b/runtime/capsules/src/mctp/mux.rs @@ -377,9 +377,7 @@ impl<'a, M: MCTPTransportBinding<'a>> TransportRxClient for MuxMCTPDriver<'a, M> return; } - // println!("MuxMCTPDriver: Received packet of {:X?}", rx_buffer); let (mctp_header, msg_type, payload_offset) = self.interpret_packet(&rx_buffer[0..len]); - println!("MuxMCTPDriver: Received packet. msg_type: {:?}", msg_type); if let Some(msg_type) = msg_type { match msg_type { MessageType::MctpControl => { diff --git a/runtime/capsules/src/test/mctp.rs b/runtime/capsules/src/test/mctp.rs index 0f8b6b7..fffa4f0 100644 --- a/runtime/capsules/src/test/mctp.rs +++ b/runtime/capsules/src/test/mctp.rs @@ -3,6 +3,7 @@ use crate::mctp::base_protocol::{MessageType, MCTP_TAG_MASK, MCTP_TAG_OWNER, MCTP_TEST_MSG_TYPE}; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; +use crate::test; use core::cell::Cell; use core::fmt::Write; @@ -13,10 +14,12 @@ use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; pub const MCTP_TEST_REMOTE_EID: u8 = 0x20; -pub const MCTP_TEST_MSG_SIZE: usize = 256; +pub const MCTP_TEST_MSG_SIZE: usize = 1000; + +static TEST_MSG_LEN_ARR: [usize; 4] = [64, 63, 256, 1000]; pub trait TestClient { - fn test_result(&self, passed: bool); + fn test_result(&self, passed: bool, npassed: usize, ntotal: usize); } pub struct MockMctp<'a> { @@ -25,6 +28,7 @@ pub struct MockMctp<'a> { msg_type: MessageType, msg_tag: Cell, test_client: OptionalCell<&'a dyn TestClient>, + cur_idx : Cell, } impl<'a> MockMctp<'a> { @@ -39,6 +43,7 @@ impl<'a> MockMctp<'a> { msg_type, msg_tag: Cell::new(0), test_client: OptionalCell::empty(), + cur_idx: Cell::new(0), } } @@ -46,20 +51,20 @@ impl<'a> MockMctp<'a> { self.test_client.set(test_client); } - fn prepare_send_data(&self) { + fn prepare_send_data(&self, msg_len: usize) { + assert!(self.mctp_msg_buf.map(|buf| buf.len()).unwrap() >= msg_len); self.mctp_msg_buf.map(|buf| { buf.reset(); buf[0] = MCTP_TEST_MSG_TYPE; - for i in 1..buf.len() { + for i in 1..msg_len { buf[i] = i as u8; } + buf.slice(0..msg_len) }); } pub fn run_send_loopback_test(&self) { - self.prepare_send_data(); - println!("run_send_loopback_test Sending message"); - assert!(self.mctp_msg_buf.map(|buf| buf.len()).unwrap() == MCTP_TEST_MSG_SIZE); + self.prepare_send_data(TEST_MSG_LEN_ARR[self.cur_idx.get()]); self.mctp_sender .send_msg( self.msg_type as u8, @@ -74,31 +79,46 @@ impl<'a> MockMctp<'a> { impl<'a> MCTPRxClient for MockMctp<'a> { fn receive(&self, src_eid: u8, msg_type: u8, msg_tag: u8, msg_payload: &[u8], msg_len: usize) { println!( - "Received message from EID: {} with message type: {} and message tag: {}", - src_eid, msg_type, msg_tag + "Received message from EID: {} with message type: {} and message tag: {} msg_len: {}", + src_eid, msg_type, msg_tag, msg_len ); if msg_type != self.msg_type as u8 || src_eid != MCTP_TEST_REMOTE_EID || msg_tag != self.msg_tag.get() - || msg_len != MCTP_TEST_MSG_SIZE + || msg_len != TEST_MSG_LEN_ARR[self.cur_idx.get()] { self.test_client.map(|client| { - client.test_result(false); + client.test_result(false, self.cur_idx.get() + 1, TEST_MSG_LEN_ARR.len()); }); } self.mctp_msg_buf.map(|buf| { if buf[..msg_len] != msg_payload[..msg_len] { self.test_client.map(|client| { - client.test_result(false); + client.test_result(false, self.cur_idx.get() + 1, TEST_MSG_LEN_ARR.len()); }); } }); + + println!("Completed loopback test for message length: {}", TEST_MSG_LEN_ARR[self.cur_idx.get()]); - self.test_client.map(|client| { - client.test_result(true); - }); + if self.cur_idx.get() == TEST_MSG_LEN_ARR.len() - 1 { + self.test_client.map(|client| { + client.test_result(true, self.cur_idx.get() + 1, TEST_MSG_LEN_ARR.len()); + }); + } else { + self.cur_idx.set(self.cur_idx.get() + 1); + self.prepare_send_data(TEST_MSG_LEN_ARR[self.cur_idx.get()]); + self.mctp_sender + .send_msg( + self.msg_type as u8, + MCTP_TEST_REMOTE_EID, + MCTP_TAG_OWNER, + self.mctp_msg_buf.take().unwrap(), + ) + .unwrap(); + } } } @@ -117,6 +137,6 @@ impl<'a> MCTPTxClient for MockMctp<'a> { self.msg_tag.set(msg_tag & MCTP_TAG_MASK); msg_payload.reset(); self.mctp_msg_buf.replace(msg_payload); - println!("Message sent"); + println!("Message sent of length : {}", TEST_MSG_LEN_ARR[self.cur_idx.get()]); } } diff --git a/runtime/i3c/src/core.rs b/runtime/i3c/src/core.rs index 039862a..f304788 100644 --- a/runtime/i3c/src/core.rs +++ b/runtime/i3c/src/core.rs @@ -21,9 +21,6 @@ use registers_generated::i3c::I3C_CSR_ADDR; use tock_registers::register_bitfields; use tock_registers::LocalRegisterCopy; -use core::fmt::Write; -use romtime::println; - pub const I3C_BASE: StaticRef = unsafe { StaticRef::new(I3C_CSR_ADDR as *const I3c) }; pub const MDB_PENDING_READ_MCTP: u8 = 0xae; pub const MAX_READ_WRITE_SIZE: usize = 250; @@ -371,7 +368,6 @@ impl<'a, A: Alarm<'a>> I3CCore<'a, A> { // called when TTI wants us to send data for a private Read pub fn handle_outgoing_read(&self) { - println!("I3C_CORE: Handling outgoing read"); self.retry_outgoing_read.set(false); if self.tx_buffer.is_none() { @@ -457,13 +453,11 @@ impl<'a, A: Alarm<'a>> crate::hil::I3CTarget<'a> for I3CCore<'a, A> { len: usize, ) -> Result<(), (ErrorCode, &'static mut [u8])> { if self.tx_buffer.is_some() { - println!("I3C_CORE: Transmitting read failed, busy"); return Err((ErrorCode::BUSY, tx_buf)); } self.tx_buffer.replace(tx_buf); self.tx_buffer_idx.set(0); self.tx_buffer_size.set(len); - println!("I3C_CORE: Transmitting read"); // TODO: check that this is for MCTP or something else self.send_ibi(MDB_PENDING_READ_MCTP); Ok(()) diff --git a/runtime/src/components/mock_mctp.rs b/runtime/src/components/mock_mctp.rs index 62ac82c..2c11734 100644 --- a/runtime/src/components/mock_mctp.rs +++ b/runtime/src/components/mock_mctp.rs @@ -5,7 +5,8 @@ use capsules_runtime::mctp::mux::MuxMCTPDriver; use capsules_runtime::mctp::recv::MCTPRxState; use capsules_runtime::mctp::send::{MCTPSender, MCTPTxState}; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; -use capsules_runtime::test::mctp::{MockMctp, MCTP_TEST_MSG_SIZE}; +use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; +use capsules_runtime::test::mctp::MockMctp; use kernel::component::Component; use kernel::utilities::leasable_buffer::SubSliceMut; @@ -20,12 +21,12 @@ macro_rules! mock_mctp_component_static { use capsules_runtime::mctp::send::MCTPTxState; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; use capsules_runtime::test::mctp::MockMctp; - use capsules_runtime::test::mctp::MCTP_TEST_MSG_SIZE; + use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; let tx_state = kernel::static_buf!(MCTPTxState<'static, MCTPI3CBinding<'static>>); let rx_state = kernel::static_buf!(MCTPRxState<'static>); - let rx_msg_buf = kernel::static_buf!([u8; MCTP_TEST_MSG_SIZE]); - let tx_msg_buf = kernel::static_buf!([u8; MCTP_TEST_MSG_SIZE]); + let rx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); + let tx_msg_buf = kernel::static_buf!([u8; MCTP_MAX_MESSAGE_SIZE]); let msg_types = kernel::static_buf!([MessageType; 1]); let mock_mctp = kernel::static_buf!(MockMctp<'static>); ( @@ -36,7 +37,6 @@ macro_rules! mock_mctp_component_static { pub struct MockMctpComponent { mctp_mux: &'static MuxMCTPDriver<'static, MCTPI3CBinding<'static>>, - // msg_types: &'static [u8], } impl MockMctpComponent { @@ -49,16 +49,16 @@ impl Component for MockMctpComponent { type StaticInput = ( &'static mut MaybeUninit>>, &'static mut MaybeUninit>, - &'static mut MaybeUninit<[u8; MCTP_TEST_MSG_SIZE]>, - &'static mut MaybeUninit<[u8; MCTP_TEST_MSG_SIZE]>, + &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, + &'static mut MaybeUninit<[u8; MCTP_MAX_MESSAGE_SIZE]>, &'static mut MaybeUninit<[MessageType; 1]>, &'static mut MaybeUninit>, ); type Output = &'static MockMctp<'static>; fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output { - let rx_msg_buf = static_buffer.2.write([0; MCTP_TEST_MSG_SIZE]); - let tx_msg_buf = static_buffer.3.write([0; MCTP_TEST_MSG_SIZE]); + let rx_msg_buf = static_buffer.2.write([0; MCTP_MAX_MESSAGE_SIZE]); + let tx_msg_buf = static_buffer.3.write([0; MCTP_MAX_MESSAGE_SIZE]); let tx_state = static_buffer.0.write(MCTPTxState::new(self.mctp_mux)); diff --git a/runtime/src/tests/mctp_test.rs b/runtime/src/tests/mctp_test.rs index 9b9c507..86dfb3f 100644 --- a/runtime/src/tests/mctp_test.rs +++ b/runtime/src/tests/mctp_test.rs @@ -35,12 +35,15 @@ impl<'a> TestMctp<'a> { } impl<'a> TestClient for TestMctp<'a> { - fn test_result(&self, passed: bool) { + fn test_result(&self, passed: bool, npassed: usize, ntotal: usize) { + println!("MCTP test result: {}/{} passed", npassed, ntotal); + println!( + "MCTP test result: {}", + if passed { "PASSED" } else { "FAILED" } + ); if passed { - println!("MCTP test passed"); crate::io::exit_emulator(0); } else { - println!("MCTP test failed"); crate::io::exit_emulator(1); } } From 1f646cf5e2720d272de55eb31b8ea834755df43f Mon Sep 17 00:00:00 2001 From: Parvathi Bhogaraju Date: Tue, 17 Dec 2024 15:45:57 -0800 Subject: [PATCH 11/11] format fixes --- runtime/capsules/src/test/mctp.rs | 21 ++++++++++++--------- runtime/src/components/mock_mctp.rs | 8 +++----- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/runtime/capsules/src/test/mctp.rs b/runtime/capsules/src/test/mctp.rs index fffa4f0..5e3996c 100644 --- a/runtime/capsules/src/test/mctp.rs +++ b/runtime/capsules/src/test/mctp.rs @@ -3,15 +3,12 @@ use crate::mctp::base_protocol::{MessageType, MCTP_TAG_MASK, MCTP_TAG_OWNER, MCTP_TEST_MSG_TYPE}; use crate::mctp::recv::MCTPRxClient; use crate::mctp::send::{MCTPSender, MCTPTxClient}; -use crate::test; - use core::cell::Cell; use core::fmt::Write; -use romtime::println; - use kernel::utilities::cells::{MapCell, OptionalCell}; use kernel::utilities::leasable_buffer::SubSliceMut; use kernel::ErrorCode; +use romtime::println; pub const MCTP_TEST_REMOTE_EID: u8 = 0x20; pub const MCTP_TEST_MSG_SIZE: usize = 1000; @@ -28,7 +25,7 @@ pub struct MockMctp<'a> { msg_type: MessageType, msg_tag: Cell, test_client: OptionalCell<&'a dyn TestClient>, - cur_idx : Cell, + cur_idx: Cell, } impl<'a> MockMctp<'a> { @@ -89,7 +86,7 @@ impl<'a> MCTPRxClient for MockMctp<'a> { || msg_len != TEST_MSG_LEN_ARR[self.cur_idx.get()] { self.test_client.map(|client| { - client.test_result(false, self.cur_idx.get() + 1, TEST_MSG_LEN_ARR.len()); + client.test_result(false, self.cur_idx.get() + 1, TEST_MSG_LEN_ARR.len()); }); } @@ -100,8 +97,11 @@ impl<'a> MCTPRxClient for MockMctp<'a> { }); } }); - - println!("Completed loopback test for message length: {}", TEST_MSG_LEN_ARR[self.cur_idx.get()]); + + println!( + "Completed loopback test for message length: {}", + TEST_MSG_LEN_ARR[self.cur_idx.get()] + ); if self.cur_idx.get() == TEST_MSG_LEN_ARR.len() - 1 { self.test_client.map(|client| { @@ -137,6 +137,9 @@ impl<'a> MCTPTxClient for MockMctp<'a> { self.msg_tag.set(msg_tag & MCTP_TAG_MASK); msg_payload.reset(); self.mctp_msg_buf.replace(msg_payload); - println!("Message sent of length : {}", TEST_MSG_LEN_ARR[self.cur_idx.get()]); + println!( + "Message sent of length : {}", + TEST_MSG_LEN_ARR[self.cur_idx.get()] + ); } } diff --git a/runtime/src/components/mock_mctp.rs b/runtime/src/components/mock_mctp.rs index 2c11734..cd061b4 100644 --- a/runtime/src/components/mock_mctp.rs +++ b/runtime/src/components/mock_mctp.rs @@ -1,27 +1,25 @@ // Licensed under the Apache-2.0 license use capsules_runtime::mctp::base_protocol::MessageType; +use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; use capsules_runtime::mctp::mux::MuxMCTPDriver; use capsules_runtime::mctp::recv::MCTPRxState; use capsules_runtime::mctp::send::{MCTPSender, MCTPTxState}; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; -use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; use capsules_runtime::test::mctp::MockMctp; - +use core::mem::MaybeUninit; use kernel::component::Component; use kernel::utilities::leasable_buffer::SubSliceMut; -use core::mem::MaybeUninit; - #[macro_export] macro_rules! mock_mctp_component_static { () => {{ use capsules_runtime::mctp::base_protocol::MessageType; + use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; use capsules_runtime::mctp::recv::MCTPRxState; use capsules_runtime::mctp::send::MCTPTxState; use capsules_runtime::mctp::transport_binding::MCTPI3CBinding; use capsules_runtime::test::mctp::MockMctp; - use capsules_runtime::mctp::driver::MCTP_MAX_MESSAGE_SIZE; let tx_state = kernel::static_buf!(MCTPTxState<'static, MCTPI3CBinding<'static>>); let rx_state = kernel::static_buf!(MCTPRxState<'static>);