1# OpenBMC platform communication channel: MCTP & PLDM in userspace 2 3Author: Jeremy Kerr <jk@ozlabs.org> <jk> 4 5Please refer to the [MCTP Overview](mctp.md) document for general MCTP design 6description, background and requirements. 7 8This document describes a userspace implementation of MCTP infrastructure, 9allowing a straightforward mechanism of supporting MCTP messaging within an 10OpenBMC system. 11 12## Proposed Design 13 14The MCTP core specification just provides the packetisation, routing and 15addressing mechanisms. The actual transmit/receive of those packets is up to 16the hardware binding of the MCTP transport. 17 18For OpenBMC, we would introduce a MCTP daemon, which implements the transport 19over a configurable hardware channel (eg., Serial UART, I2C or PCIe), and 20provides a socket-based interface for other processes to send and receive 21complete MCTP messages. This daemon is responsible for the packetisation and 22routing of MCTP messages from external endpoints, and handling the forwarding 23these messages to and from individual handler applications. This includes 24handling local MCTP-stack configuration, like local EID assignments. 25 26This daemon has a few components: 27 281. the core MCTP stack 29 302. one or more binding implementations (eg, MCTP-over-serial), which interact 31 with the hardware channel(s). 32 333. an interface to handler applications over a unix-domain socket. 34 35The proposed implementation here is to produce an MCTP "library" which provides 36the packetisation and routing functions, between: 37 38- an "upper" messaging transmit/receive interface, for tx/rx of a full message 39 to a specific endpoint (ie, (1) above) 40 41- a "lower" hardware binding for transmit/receive of individual packets, 42 providing a method for the core to tx/rx each packet to hardware, and defines 43 the parameters of the common packetisation code (ie. (2) above). 44 45The lower interface would be plugged in to one of a number of hardware-specific 46binding implementations. Most of these would be included in the library source 47tree, but others can be plugged-in too, perhaps where the physical layer 48implementation does not make sense to include in the platform-agnostic library. 49 50The reason for a library is to allow the same MCTP implementation to be used in 51both OpenBMC and host firmware; the library should be bidirectional. To allow 52this, the library would be written in portable C (structured in a way that can 53be compiled as "extern C" in C++ codebases), and be able to be configured to 54suit those runtime environments (for example, POSIX IO may not be available on 55all platforms; we should be able to compile the library to suit). The licence 56for the library should also allow this re-use; a dual Apache & GPLv2+ licence 57may be best. 58 59These "lower" binding implementations may have very different methods of 60transferring packets to the physical layer. For example, a serial binding 61implementation for running on a Linux environment may be implemented through 62read()/write() syscalls to a PTY device. An I2C binding for use in low-level 63host firmware environments may interact directly with hardware registers to 64perform packet transfers. 65 66The application-specific handlers implement the actual functionality provided 67over the MCTP channel, and connect to the central daemon over a UNIX domain 68socket. Each of these would register with the MCTP daemon to receive MCTP 69messages of a certain type, and would transmit MCTP messages of that same type. 70 71The daemon's sockets to these handlers is configured for non-blocking IO, to 72allow the daemon to be decoupled from any blocking behaviour of handlers. The 73daemon would use a message queue to enable message reception/transmission to a 74blocked daemon, but this would be of a limited size. Handlers whose sockets 75exceed this queue would be disconnected from the daemon. 76 77One design intention of the multiplexer daemon is to allow a future 78kernel-based MCTP implementation without requiring major structural changes to 79handler applications. The socket-based interface facilitates this, as the 80unix-domain socket interface could be fairly easily swapped out with a new 81kernel-based socket type. 82 83MCTP is intended to be an optional component of OpenBMC. Platforms using 84OpenBMC are free to adopt it as they see fit. 85 86### Demultiplexer daemon interface 87 88MCTP handlers (ie, clients of the demultiplexer) connect using a unix-domain 89socket, at the abstract socket address: 90 91``` 92\0mctp-demux 93``` 94 95The socket type used should be `SOCK_SEQPACKET`. 96 97Once connected, the client sends a single byte message, indicating what type of 98MCTP messages should be forwarded to the client. Types must be greater than 99zero. 100 101Subsequent messages sent over the socket are MCTP messages sent/received by the 102demultiplexer, that match the specified MCTP message type. Clients should use 103the send/recv syscalls to interact with the socket. 104 105Each message has a fixed small header: 106 107``` 108uint8_t eid 109``` 110 111For messages coming from the demux daemon, this indicates the source EID of the 112outgoing MCTP message. For messages going to the demux daemon, this indicates 113the destination EID. 114 115The rest of the message data is the complete MCTP message, including MCTP 116message type field. 117 118The daemon does not provide a facility for clients to specify or retrieve 119values for the tag field in individual MCTP packets. 120 121 122## Alternatives Considered 123 124In terms of an MCTP daemon structure, an alternative is to have the MCTP 125implementation contained within a single process, using the libmctp API 126directly for passing messages from the core code to application-level handlers. 127The drawback of this approach is that this single process needs to implement 128all possible functionality that is available over MCTP, which may be quite a 129disjoint set. This would likely lead to unnecessary restrictions on the 130implementation of those application-level handlers (programming language, 131frameworks used, etc). Also, this single-process approach would likely need 132more significant modifications if/when MCTP protocol support is moved to the 133kernel. 134 135The interface between the demultiplexer daemon and clients is currently defined 136as a socket-based interface. However, an alternative here would be to pass MCTP 137messages over dbus instead. The reason for the choice of sockets rather than 138dbus is that the former allows a direct transition to a kernel-based socket API 139when suitable. 140 141## Testing 142 143For the core MCTP library, we are able to run tests there in complete isolation 144(I have already been able to run a prototype MCTP stack through the afl fuzzer) 145to ensure that the core transport protocol works. 146 147For MCTP hardware bindings, we would develop channel-specific tests that would 148be run in CI on both host and BMC. 149 150For the OpenBMC MCTP daemon implementation, testing models would depend on the 151structure we adopt in the design section. 152