Crate mctp_rs

Source
Expand description

§mctp-rs

A no_std Rust implementation of the DMTF Management Component Transport Protocol (MCTP) transport.

§Receiving and parsing messages

Use MctpPacketContext with your medium to assemble messages from packets.

let mut assembly_buffer = [0u8; 1024];
let medium = MyMedium { mtu: 256 };
let mut context = MctpPacketContext::new(medium, &mut assembly_buffer);

// Typically obtained from your bus
let raw_packet_data: &[u8] = &[0x01, 0x02, 0x03, 0x83];

match context.deserialize_packet(raw_packet_data) {
    Ok(Some(message)) => {
        // We received a complete MCTP message
        if let Ok((header, control)) = message.parse_as::<MctpControl>() {
            match control {
                MctpControl::GetEndpointIdRequest => {
                    // Handle control request
                    let _instance = header.instance_id;
                }
                MctpControl::GetEndpointIdResponse(bytes3) => {
                    // Use response payload (3 bytes as per spec)
                    let _eid = bytes3[0];
                }
                _ => {}
            }
        }
    }
    Ok(None) => { /* partial message; wait for more packets */ }
    Err(e) => {
        // handle protocol/medium error
        let _ = e;
    }
}

§Sending messages

Construct a header + body pair implementing MctpMessageTrait and serialize to one or more packets using serialize_packet.

let mut buf = [0u8; 1024];
let mut ctx = MctpPacketContext::new(MyMedium { mtu: 64 }, &mut buf);

let reply = MctpReplyContext {
    destination_endpoint_id: EndpointId::try_from(0x20).unwrap(),
    source_endpoint_id: EndpointId::try_from(0x21).unwrap(),
    packet_sequence_number: MctpSequenceNumber::new(0),
    message_tag: MctpMessageTag::try_from(1).unwrap(),
    medium_context: (),
};

let message = (
    VendorDefinedPciHeader(0x1234),
    VendorDefinedPci(&[0xDE, 0xAD, 0xBE, 0xEF]),
);

let mut packets = ctx.serialize_packet(reply, message).unwrap();
while let Some(packet_result) = packets.next() {
    let packet_bytes = packet_result.unwrap();
    // send `packet_bytes` via your bus
    let _ = packet_bytes;
}

§Implementing a custom medium

The crate is transport-agnostic via the MctpMedium trait. Implement it for your bus (e.g., SMBus, eSPI) and provide a frame type implementing MctpMediumFrame.

use mctp_rs::*;

#[derive(Debug, Clone, Copy)]
struct MyMedium {
    mtu: usize,
}

#[derive(Debug, Clone, Copy)]
struct MyMediumFrame {
    packet_size: usize,
}

impl MctpMedium for MyMedium {
    type Frame = MyMediumFrame;
    type Error = &'static str;
    type ReplyContext = ();

    fn max_message_body_size(&self) -> usize {
        self.mtu
    }

    fn deserialize<'buf>(
        &self,
        packet: &'buf [u8],
    ) -> MctpPacketResult<(Self::Frame, &'buf [u8]), Self> {
        // Strip/validate transport headers as needed for your bus and return MCTP payload slice
        Ok((
            MyMediumFrame {
                packet_size: packet.len(),
            },
            packet,
        ))
    }

    fn serialize<'buf, F>(
        &self,
        _reply_context: Self::ReplyContext,
        buffer: &'buf mut [u8],
        message_writer: F,
    ) -> MctpPacketResult<&'buf [u8], Self>
    where
        F: for<'a> FnOnce(&'a mut [u8]) -> MctpPacketResult<usize, Self>,
    {
        // Prepend transport headers as needed, then ask the writer to write MCTP payload
        let message_len = message_writer(buffer)?;
        Ok(&buffer[..message_len])
    }
}

impl MctpMediumFrame<MyMedium> for MyMediumFrame {
    fn packet_size(&self) -> usize {
        self.packet_size
    }
    fn reply_context(&self) -> <MyMedium as MctpMedium>::ReplyContext {
        ()
    }
}

Re-exports§

pub use error::MctpPacketError;
pub use error::MctpPacketResult;

Modules§

error
mctp_completion_code
smbus_espi

Structs§

MctpControlHeader
MctpMessage
MctpMessageBuffer
MctpMessageTag
MctpPacketContext
Context for serializing and deserializing an MCTP message, which may be split among multiple packets.
MctpReplyContext
Represents the state needed to construct a repsonse to a request: the MCTP transport source/destination, the sequence number to use for the reply, and the medium-specific context that came with the request.
MctpSequenceNumber
VendorDefinedPci
VendorDefinedPciHeader

Enums§

EndpointId
MctpControl

Traits§

MctpMedium
MctpMediumFrame
MctpMessageHeaderTrait
MctpMessageTrait