blob: 2cfed72fd4bd5af7c7aa1bf5c12621c5337ef21f [file] [view]
# openprot-mctp-server
Platform-independent MCTP server core, ported from the Hubris `mctp-server` crate.
## Overview
This crate implements the central MCTP server logic: listener and request handle allocation, inbound message routing, outbound message fragmentation/sending, and timeout management for pending receive calls. It is generic over transport bindings via the `mctp_lib::Sender` trait.
## Key Types
- `Server<S, N>` the MCTP server, generic over `Sender` (transport) and `N` (config)
- `ServerConfig` configuration constants (MAX_REQUESTS: 8, MAX_LISTENERS: 8, MAX_OUTSTANDING: 16, MAX_PAYLOAD: 1023)
- `RecvResult` result from a receive operation
## Modules
- `dispatch` IPC request dispatcher; decodes wire-protocol requests and calls the corresponding `Server` methods
## Architecture
The server wraps the `mctp-lib` `Router` as its packet processing engine. Inbound packets are fed via `Server::inbound()`, and `Server::update()` drives pending-recv fulfillment. The `dispatch` module bridges IPC wire-protocol messages to server operations.
## Dependencies
- `openprot-mctp-api` API traits and wire protocol
- `mctp-lib` `Router`, `Sender`, fragmentation, serial/I2C handlers
- `mctp` core MCTP types (`Eid`, `MsgType`, `Tag`)
- `heapless` `no_std` collections
## Building the MCTP Echo System Image
The MCTP echo demo is a 3-application system image for the AST1060-EVB (640KB usable SRAM):
```
Flash (512KB) RAM (128KB)
0x00000 ┌─────────────────────┐ 0x80000 ┌──────────────────┐
│ pw_kernel (~128KB) │ │ i2c_server 32KB │
0x20000 ├─────────────────────┤ 0x88000 ├──────────────────┤
│ i2c_server 128KB │ │ mctp_server 32KB │
0x40000 ├─────────────────────┤ 0x90000 ├──────────────────┤
│ mctp_server 128KB │ │ mctp_echo 32KB │
0x60000 ├─────────────────────┤ 0x98000 ├──────────────────┤
│ mctp_echo 128KB │ │ kernel 32KB │
0x80000 └─────────────────────┘ 0xA0000 └──────────────────┘
(640KB = 0xA0000)
```
| App | Source | Role |
|-----|--------|------|
| `i2c_server` | `//services/i2c/server` | I2C transport backend |
| `mctp_server` | `//services/mctp/server` | MCTP router + IPC dispatcher |
| `mctp_echo` | `//target/ast1060-evb/mctp/mctp_echo.rs` | Listens for type-1 messages, echoes payload back |
### Build the full system image
```sh
bazel build --config=k_ast1060_evb //target/ast1060-evb/mctp:mctp
```
### Build just the echo binary
```sh
bazel build --config=k_ast1060_evb //target/ast1060-evb/mctp:mctp_echo
```
### Build a UART-bootable image (for physical EVB)
```sh
bazel build --config=k_ast1060_evb //target/ast1060-evb/mctp:mctp_uart
```
The output binary `mctp_uart.bin` can be flashed over the UART boot interface.
### Run the system image test
```sh
bazel test --config=k_ast1060_evb //target/ast1060-evb/mctp:mctp_test
```
> The `mctp_test` rule wraps the system image in a `system_image_test` harness that
> exercises the full kernel + I2C server + MCTP server + echo app stack.
---
## Tests
The `tests/` directory contains integration tests that run on the host (std) with **no I2C transport** a `BufferSender` mock replaces it entirely.
### Test files
| File | What it tests |
|------|---------------|
| `tests/common/mod.rs` | Shared fixtures: `BufferSender`, `DroppingBufferSender`, `DirectClient`, `DirectListener`, `DirectRespChannel`, `DirectReqChannel` |
| `tests/echo.rs` | Full MCTP echo round-trip via `MctpClient` trait |
| `tests/dispatch.rs` | IPC wire-protocol dispatch: encodes requests, calls `dispatch_mctp_op`, verifies responses. Includes edge cases: malformed request, unknown opcode, `Recv` with no message, `Unbind` |
| `tests/server_unit.rs` | Unit tests for `Server` methods: EID management, handle allocation, `try_recv` before/after `inbound`, oversized payload, timeout via `register_recv` + `update` |
| `tests/integration.rs` | Multi-fragment reassembly, multiple concurrent listeners (no cross-talk), echo via `MctpListener` + `MctpRespChannel` traits, `MctpReqChannel` trait, `drop_handle` mid-flight, response EID/tag threading |
The echo via `MctpListener` + `MctpRespChannel` test (`echo_via_mctplistener_trait`) is the key one: it exercises the exact interface the real echo application uses, with `BufferSender` as the only transport.
### Running with Bazel
```sh
# Run all test targets
bazel test //services/mctp/server:mctp_server_echo_test \
//services/mctp/server:mctp_server_dispatch_test \
//services/mctp/server:mctp_server_unit_test \
//services/mctp/server:mctp_server_integration_test
# Show test output
bazel test //services/mctp/server:mctp_server_unit_test --test_output=all
```
> **Note:** Do not use the `//services/mctp/...` wildcard it will also pick up
> the `mctp_server` and `mctp_echo` kernel binaries, which require `kernel_config`
> (generated only during a full system image build). Target the test rules directly
> as shown above.